From 2871fc670f448e5f7cab7101479cb5b88e4d21f4 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 21 May 2021 00:19:34 +0700 Subject: [PATCH 01/13] initial serialization of TLS session --- configure.ac | 4 - src/internal.c | 728 +++++++++++++++++++++++++++++---------------- src/ssl.c | 49 ++- tests/api.c | 14 +- wolfssl/internal.h | 30 +- wolfssl/ssl.h | 3 + 6 files changed, 552 insertions(+), 276 deletions(-) diff --git a/configure.ac b/configure.ac index b417a3b43..54549f2fa 100644 --- a/configure.ac +++ b/configure.ac @@ -6013,10 +6013,6 @@ AC_ARG_ENABLE([sessionexport], if test "$ENABLED_SESSIONEXPORT" = "yes" || test "$ENABLED_SESSIONEXPORT" = "nopeer" then - if test "$ENABLED_DTLS" = "no" - then - AC_MSG_ERROR([Only DTLS supported with session export]) - fi AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SESSION_EXPORT" if test "$ENABLED_SESSIONEXPORT" = "nopeer" diff --git a/src/internal.c b/src/internal.c index 45e47c103..4c5af8058 100644 --- a/src/internal.c +++ b/src/internal.c @@ -585,9 +585,12 @@ static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) #ifdef WOLFSSL_SESSION_EXPORT -#ifdef WOLFSSL_DTLS -/* serializes the cipher specs struct for exporting */ -static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +/** + * serializes the cipher specs struct for exporting + * @return the amount written to 'exp' buffer + */ +static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, + int isTLS) { word32 idx = 0; CipherSpecs* specs; @@ -600,11 +603,11 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) specs= &(ssl->specs); - if (DTLS_EXPORT_SPC_SZ > len) { + if (WOLFSSL_EXPORT_SPC_SZ > len) { return BUFFER_E; } - XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ); + XMEMSET(exp, 0, WOLFSSL_EXPORT_SPC_SZ); c16toa(specs->key_size, exp + idx); idx += OPAQUE16_LEN; c16toa(specs->iv_size, exp + idx); idx += OPAQUE16_LEN; @@ -619,11 +622,27 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = specs->pad_size; exp[idx++] = specs->static_ecdh; - if (idx != DTLS_EXPORT_SPC_SZ) { - WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version"); + if (idx != WOLFSSL_EXPORT_SPC_SZ) { + WOLFSSL_MSG("WOLFSSL_EXPORT_SPC_SZ needs updated and export version"); return DTLS_EXPORT_VER_E; } + /* send over state of AES too */ + if (isTLS && ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { + byte *pt = (byte*)ssl->encrypt.aes->reg; + + if ((idx + 2*AES_BLOCK_SIZE) > len) { + WOLFSSL_MSG("Can not fit AES state into buffer\n"); + return BUFFER_E; + } + XMEMCPY(exp + idx, pt, AES_BLOCK_SIZE); + idx += AES_BLOCK_SIZE; + + pt = (byte*)ssl->decrypt.aes->reg; + XMEMCPY(exp + idx, pt, AES_BLOCK_SIZE); + idx += AES_BLOCK_SIZE; + } + WOLFSSL_LEAVE("ExportCipherSpecState", idx); (void)ver; return idx; @@ -632,7 +651,7 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) /* serializes the key struct for exporting */ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, - byte small) + byte small, int isTLS) { word32 idx = 0; byte sz; @@ -658,6 +677,8 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + #if defined(WOLFSSL_DTLS) + if (!isTLS) { c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN; c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; @@ -677,6 +698,8 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN; c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN; + } + #endif c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN; c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN; exp[idx++] = keys->encryptionOn; @@ -684,7 +707,8 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, /* from here on the buffer needs checked because is variable length that * can be larger than DTLS_EXPORT_MIN_KEY_SZ */ - { +#ifdef WOLFSSL_DTLS + if (!isTLS) { word32 i; if ((OPAQUE16_LEN * 2) + idx + (2 * (WOLFSSL_DTLS_WINDOW_WORDS * OPAQUE32_LEN)) > len) { @@ -703,6 +727,7 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, idx += OPAQUE32_LEN; } } +#endif if (idx >= len) { WOLFSSL_MSG("Buffer not large enough for truncated hmac flag"); @@ -779,13 +804,30 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, WOLFSSL_LEAVE("ExportKeyState", idx); (void)ver; + (void)isTLS; return idx; } -static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) + +/** + * Imports the buffer 'exp' into the 'ssl' CipherSpec structure. + * @param ssl WOLFSSL structure to import into + * @param exp input buffer to read from + * @param len length of exp buffer + * @param ver version of import buffer found + * @param isTLS flag for importing a TLS session or DTLS + * + * @return size of exp buffer consumed on success and negative value on fail + */ +static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, + byte ver, int isTLS) { word32 idx = 0; CipherSpecs* specs; + word32 tmp_seq_peer_lo; + word32 tmp_seq_peer_hi; + word32 tmp_seq_lo; + word32 tmp_seq_hi; WOLFSSL_ENTER("ImportCipherSpecState"); @@ -795,7 +837,7 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, byte specs= &(ssl->specs); - if (DTLS_EXPORT_SPC_SZ > len) { + if (WOLFSSL_EXPORT_SPC_SZ > len) { WOLFSSL_MSG("Buffer not large enough for max spec struct size"); return BUFFER_E; } @@ -813,17 +855,53 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, byte specs->pad_size = exp[idx++]; specs->static_ecdh = exp[idx++]; + /* temporarly save the sequence numbers */ + tmp_seq_peer_lo = ssl->keys.peer_sequence_number_lo; + tmp_seq_peer_hi = ssl->keys.peer_sequence_number_hi; + tmp_seq_lo = ssl->keys.sequence_number_lo; + tmp_seq_hi = ssl->keys.sequence_number_hi; + + SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); + + /* reset sequence numbers after setting keys */ + ssl->keys.peer_sequence_number_lo = tmp_seq_peer_lo; + ssl->keys.peer_sequence_number_hi = tmp_seq_peer_hi; + ssl->keys.sequence_number_lo = tmp_seq_lo; + ssl->keys.sequence_number_hi = tmp_seq_hi; + + if (isTLS && ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { + byte *pt = (byte*)ssl->encrypt.aes->reg; + XMEMCPY(pt, exp + idx, AES_BLOCK_SIZE); + idx += AES_BLOCK_SIZE; + + pt = (byte*)ssl->decrypt.aes->reg; + XMEMCPY(pt, exp + idx, AES_BLOCK_SIZE); + idx += AES_BLOCK_SIZE; + } + WOLFSSL_LEAVE("ImportCipherSpecState", idx); (void)ver; return idx; } -static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) +/** + * Import the Key structure + * + * @param ssl WOLFSSL structure to import into + * @param exp buffer to read Key values from + * @param len max length of buffer 'exp' + * @param ver version of import buffer found + * @param isTLS flag for TLS vs DTLS + * + * @return amount of data read from exp on success or negative on fail + */ +static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, + int isTLS) { word32 idx = 0; - byte sz; - Keys* keys; + byte sz; + Keys *keys; WOLFSSL_ENTER("ImportKeyState"); @@ -843,31 +921,39 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN; ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN; + #if defined(WOLFSSL_DTLS) + if (!isTLS) { + ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->dtls_expected_peer_handshake_number); - idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->dtls_peer_handshake_number); + idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->dtls_expected_peer_handshake_number); + idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->dtls_sequence_number_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->dtls_sequence_number_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->dtls_epoch); idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->dtls_handshake_number); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->encryptSz); idx += OPAQUE32_LEN; - ato32(exp + idx, &keys->padSz); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_sequence_number_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->dtls_sequence_number_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); + idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); + idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_epoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->dtls_handshake_number); idx += OPAQUE16_LEN; + } + #endif + ato32(exp + idx, &keys->encryptSz); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->padSz); idx += OPAQUE32_LEN; keys->encryptionOn = exp[idx++]; keys->decryptedCur = exp[idx++]; - { + #if defined(WOLFSSL_DTLS) + if (!isTLS) { word16 i, wordCount, wordAdj = 0; /* do window */ @@ -903,6 +989,7 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) idx += wordAdj; } + #endif #ifdef HAVE_TRUNCATED_HMAC ssl->truncated_hmac = exp[idx++]; @@ -960,21 +1047,28 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) WOLFSSL_LEAVE("ImportKeyState", idx); (void)ver; + (void)isTLS; return idx; } /* copy over necessary information from Options struct to buffer * On success returns size of buffer used on failure returns a negative value */ -static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, + int isTLS) { - int idx = 0; - word16 zero = 0; - Options* options = &ssl->options; + int idx = 0; + word16 zero = 0; + Options *options; - WOLFSSL_ENTER("dtls_export_new"); + WOLFSSL_ENTER("ExportOptions"); - if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) { + if (ssl == NULL || exp == NULL || len < DTLS_EXPORT_OPT_SZ) { + return BAD_FUNC_ARG; + } + + options = &ssl->options; + if (options == NULL) { return BAD_FUNC_ARG; } @@ -1054,11 +1148,11 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = options->useTicket; exp[idx++] = options->noTicketTls12; #ifdef WOLFSSL_TLS13 - if (ver > DTLS_EXPORT_VERSION_3) { + if (ver > WOLFSSL_EXPORT_VERSION_3) { exp[idx++] = options->noTicketTls13; } #else - if (ver > DTLS_EXPORT_VERSION_3) { + if (ver > WOLFSSL_EXPORT_VERSION_3) { exp[idx++] = 0; } #endif @@ -1066,7 +1160,7 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = 0; exp[idx++] = 0; exp[idx++] = 0; - if (ver > DTLS_EXPORT_VERSION_3) { + if (ver > WOLFSSL_EXPORT_VERSION_3) { exp[idx++] = 0; } #endif @@ -1082,6 +1176,13 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = options->acceptState; exp[idx++] = options->asyncState; + if (isTLS) { + exp[idx++] = ssl->options.disallowEncThenMac; + exp[idx++] = ssl->options.encThenMac; + exp[idx++] = ssl->options.startedETMRead; + exp[idx++] = ssl->options.startedETMWrite; + } + /* version of connection */ exp[idx++] = ssl->version.major; exp[idx++] = ssl->version.minor; @@ -1090,15 +1191,15 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) /* check if changes were made and notify of need to update export version */ switch (ver) { - case DTLS_EXPORT_VERSION_3: + case WOLFSSL_EXPORT_VERSION_3: if (idx != DTLS_EXPORT_OPT_SZ_3) { WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); return DTLS_EXPORT_VER_E; } break; - case DTLS_EXPORT_VERSION: - if (idx != DTLS_EXPORT_OPT_SZ) { + case WOLFSSL_EXPORT_VERSION: + if (idx != DTLS_EXPORT_OPT_SZ && !isTLS) { WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); return DTLS_EXPORT_VER_E; } @@ -1109,28 +1210,30 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) return DTLS_EXPORT_VER_E; } - WOLFSSL_LEAVE("dtls_export_new", idx); + WOLFSSL_LEAVE("ExportOptions", idx); + (void)isTLS; return idx; } /* copy items from Export struct to Options struct * On success returns size of buffer used on failure returns a negative value */ -static int dtls_export_load(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) +static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, + int isTLS) { int idx = 0; Options* options = &ssl->options; switch (ver) { - case DTLS_EXPORT_VERSION: + case WOLFSSL_EXPORT_VERSION: if (len < DTLS_EXPORT_OPT_SZ) { WOLFSSL_MSG("Sanity check on buffer size failed"); return BAD_FUNC_ARG; } break; - case DTLS_EXPORT_VERSION_3: + case WOLFSSL_EXPORT_VERSION_3: if (len < DTLS_EXPORT_OPT_SZ_3) { WOLFSSL_MSG("Sanity check on buffer size failed"); return BAD_FUNC_ARG; @@ -1221,11 +1324,11 @@ static int dtls_export_load(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) options->useTicket = exp[idx++]; /* Use Ticket not session cache */ options->noTicketTls12 = exp[idx++]; /* Server won't create new Ticket */ #ifdef WOLFSSL_TLS13 - if (ver > DTLS_EXPORT_VERSION_3) { + if (ver > WOLFSSL_EXPORT_VERSION_3) { options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */ } #else - if (ver > DTLS_EXPORT_VERSION_3) { + if (ver > WOLFSSL_EXPORT_VERSION_3) { idx++; } #endif @@ -1233,7 +1336,7 @@ static int dtls_export_load(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) idx++; idx++; idx++; - if (ver > DTLS_EXPORT_VERSION_3) { + if (ver > WOLFSSL_EXPORT_VERSION_3) { idx++; } #endif @@ -1249,15 +1352,25 @@ static int dtls_export_load(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) options->acceptState = exp[idx++]; options->asyncState = exp[idx++]; + if (isTLS) { + ssl->options.disallowEncThenMac = exp[idx++]; + ssl->options.encThenMac = exp[idx++]; + ssl->options.startedETMRead = exp[idx++]; + ssl->options.startedETMWrite = exp[idx++]; + } + /* version of connection */ if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2"); return VERSION_ERROR; } + (void)isTLS; return idx; } + +#ifdef WOLFSSL_DTLS #ifndef WOLFSSL_SESSION_EXPORT_NOPEER static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) { @@ -1267,12 +1380,12 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) word16 port = 0; char ip[DTLS_EXPORT_IP]; - if (ver != DTLS_EXPORT_VERSION) { + if (ver != WOLFSSL_EXPORT_VERSION) { WOLFSSL_MSG("Export version not supported"); return BAD_FUNC_ARG; } - if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) { + if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * WOLFSSL_EXPORT_LEN) { return BAD_FUNC_ARG; } @@ -1291,10 +1404,10 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) return SOCKET_ERROR_E; } - c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN; - c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN; + c16toa((word16)fam, exp + idx); idx += WOLFSSL_EXPORT_LEN; + c16toa((word16)ipSz, exp + idx); idx += WOLFSSL_EXPORT_LEN; XMEMCPY(exp + idx, ip, ipSz); idx += ipSz; - c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN; + c16toa(port, exp + idx); idx += WOLFSSL_EXPORT_LEN; return idx; } @@ -1309,7 +1422,7 @@ static int ImportPeerInfo(WOLFSSL* ssl, const byte* buf, word32 len, byte ver) word16 port; char ip[DTLS_EXPORT_IP]; - if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) { + if (ver != WOLFSSL_EXPORT_VERSION && ver != WOLFSSL_EXPORT_VERSION_3) { WOLFSSL_MSG("Export version not supported"); return BAD_FUNC_ARG; } @@ -1319,22 +1432,22 @@ static int ImportPeerInfo(WOLFSSL* ssl, const byte* buf, word32 len, byte ver) return 0; } - if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) { + if (ssl == NULL || buf == NULL || len < 3 * WOLFSSL_EXPORT_LEN) { return BAD_FUNC_ARG; } /* import sin family */ - ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN; + ato16(buf + idx, &fam); idx += WOLFSSL_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) { + ato16(buf + idx, &ipSz); idx += WOLFSSL_EXPORT_LEN; + if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + WOLFSSL_EXPORT_LEN) > len) { return BUFFER_E; } XMEMSET(ip, 0, sizeof(ip)); XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */ - ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN; + ato16(buf + idx, &port); idx += WOLFSSL_EXPORT_LEN; /* sanity check for a function to call, then use it to import peer info */ if (ssl->ctx->CBSetPeer == NULL) { @@ -1367,9 +1480,9 @@ int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) return BAD_FUNC_ARG; } - totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */ + totalLen += WOLFSSL_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_MIN_KEY_SZ; + totalLen += WOLFSSL_EXPORT_LEN + DTLS_EXPORT_MIN_KEY_SZ; if (totalLen > sz) { WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BUFFER_E); return BUFFER_E; @@ -1377,20 +1490,20 @@ int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) 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 */ + ((byte)WOLFSSL_EXPORT_VERSION & 0X0F); + idx += WOLFSSL_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 */ + idx += WOLFSSL_EXPORT_LEN; /* leave room for length */ if ((ret = ExportKeyState(ssl, buf + idx, sz - idx, - DTLS_EXPORT_VERSION, 1)) < 0) { + WOLFSSL_EXPORT_VERSION, 1, WOLFSSL_EXPORT_DTLS)) < 0) { WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", ret); return ret; } - c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret; + c16toa((word16)ret, buf + idx - WOLFSSL_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); + c16toa((word16)(idx - WOLFSSL_EXPORT_LEN), buf + WOLFSSL_EXPORT_LEN); #ifdef WOLFSSL_SESSION_EXPORT_DEBUG /* if compiled with debug options then print the version, protocol, size */ @@ -1408,100 +1521,6 @@ int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) } -/* 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. - * On success returns the size of serialized session.*/ -int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz) -{ - int ret; - word32 idx = 0; - word32 totalLen = 0; - - WOLFSSL_ENTER("wolfSSL_dtls_export_internal"); - - if (buf == NULL || ssl == NULL) { - WOLFSSL_LEAVE("wolfSSL_dtls_export_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_OPT_SZ; - totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ; - totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ; - totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz; - - if (totalLen > sz) { - WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E); - return BUFFER_E; - } - - buf[idx++] = (byte)DTLS_EXPORT_PRO; - buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) | - ((byte)DTLS_EXPORT_VERSION & 0X0F); - - idx += DTLS_EXPORT_LEN; /* leave spot for length */ - - c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN; - if ((ret = dtls_export_new(ssl, buf + idx, sz - idx, - DTLS_EXPORT_VERSION)) < 0) { - WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); - return ret; - } - idx += ret; - - /* 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)) < 0) { - WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); - return ret; - } - c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret; - - /* export of cipher specs struct */ - c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN; - if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx, - DTLS_EXPORT_VERSION)) < 0) { - WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); - return ret; - } - idx += ret; - - /* export of dtls peer information */ - idx += DTLS_EXPORT_LEN; -#ifdef WOLFSSL_SESSION_EXPORT_NOPEER - ret = 0; /* not saving peer port/ip information */ -#else - if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx, - DTLS_EXPORT_VERSION)) < 0) { - WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); - return ret; - } -#endif - 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); - - /* if compiled with debug options then print the version, protocol, size */ -#ifdef WOLFSSL_SESSION_EXPORT_DEBUG - { - char debug[256]; - XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\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_internal", idx); - return idx; -} - - /* On success return amount of buffer consumed */ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) { @@ -1512,7 +1531,7 @@ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) WOLFSSL_ENTER("wolfSSL_dtls_import_state_internal"); /* check at least enough room for protocol and length */ - if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) { + if (sz < WOLFSSL_EXPORT_LEN * 2 || ssl == NULL) { WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", BAD_FUNC_ARG); return BAD_FUNC_ARG; } @@ -1524,8 +1543,8 @@ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) } version = buf[idx++] & 0x0F; - ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; - if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */ + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (length > sz - WOLFSSL_EXPORT_LEN) { /* subtract 2 for protocol */ WOLFSSL_MSG("Buffer size sanity check failed"); return BUFFER_E; } @@ -1543,7 +1562,7 @@ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) /* perform sanity checks and extract Options information used */ switch (version) { - case DTLS_EXPORT_VERSION: + case WOLFSSL_EXPORT_VERSION: break; default: @@ -1553,16 +1572,17 @@ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) } /* perform sanity checks and extract Keys struct */ - if (DTLS_EXPORT_LEN + idx > sz) { + if (WOLFSSL_EXPORT_LEN + idx > sz) { WOLFSSL_MSG("Import Key struct error"); return BUFFER_E; } - ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + ato16(buf + idx, &length); idx += WOLFSSL_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) { + if ((ret = ImportKeyState(ssl, buf + idx, length, version, + WOLFSSL_EXPORT_DTLS)) < 0) { WOLFSSL_MSG("Import Key struct error"); WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret); return ret; @@ -1572,36 +1592,66 @@ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret); return idx; } +#endif /* WOLFSSL_DTLS */ -/* On success return amount of buffer consumed */ -int wolfSSL_dtls_import_internal(WOLFSSL* ssl, const byte* buf, word32 sz) +/** + * Imports a serialized buffer (both TLS and DTLS) + * + * @param ssl WOLFSSL structure to import into + * @param buf buffer containing serialized session + * @param sz size of buffer 'buf' + * @param isTLS flag for TLS or DTLS + * + * @return the size of serialized buffer on success + */ +int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, + unsigned int sz, int isTLS) { word32 idx = 0; word16 length = 0; int version; - int ret; + int ret = 0; int optSz; + int rc; + byte validProto = 0; /* did we find a valid protocol */ - WOLFSSL_ENTER("wolfSSL_dtls_import_internal"); + WOLFSSL_ENTER("wolfSSL_session_import_internal"); /* check at least enough room for protocol and length */ - if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) { - return BAD_FUNC_ARG; + if (sz < WOLFSSL_EXPORT_LEN * 2 || ssl == NULL) { + ret = BAD_FUNC_ARG; } - /* sanity check on protocol ID and size of buffer */ - 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 */ + /* Check if is TLS export protocol */ + if (ret == 0) { + if (buf[idx] == (byte)TLS_EXPORT_PRO && + (buf[idx + 1] & 0xF0) == ((byte)TLS_EXPORT_PRO & 0xF0)) { + validProto = 1; + } - /* check if importing state only */ - return wolfSSL_dtls_import_state_internal(ssl, buf, sz); + /* Check if is DTLS export protocol */ + if (buf[idx] == (byte)DTLS_EXPORT_PRO && + (buf[idx + 1] & 0xF0) == ((byte)DTLS_EXPORT_PRO & 0xF0)) { + validProto = 1; + } + + if (validProto == 0) { + #ifdef WOLFSSL_DTLS + /* check if importing state only */ + return wolfSSL_dtls_import_state_internal(ssl, buf, sz); + #else + ret = BAD_FUNC_ARG; + #endif + } + idx += 1; } - version = buf[idx++] & 0x0F; - ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; - if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */ - return BUFFER_E; + if (ret == 0) { + version = buf[idx++] & 0x0F; + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (length > sz - WOLFSSL_EXPORT_LEN) { /* subtract 2 for protocol */ + ret = BUFFER_E; + } } /* if compiled with debug options then print the version, protocol, size */ @@ -1616,90 +1666,130 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, const byte* buf, word32 sz) #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ /* perform sanity checks and extract Options information used */ - switch (version) { - case DTLS_EXPORT_VERSION: - optSz = DTLS_EXPORT_OPT_SZ; - break; + if (ret == 0) { + switch (version) { + case WOLFSSL_EXPORT_VERSION: + optSz = DTLS_EXPORT_OPT_SZ; + break; - case DTLS_EXPORT_VERSION_3: - WOLFSSL_MSG("Importing older version 3"); - optSz = DTLS_EXPORT_OPT_SZ_3; - break; - - default: - WOLFSSL_MSG("Bad export version"); - return BAD_FUNC_ARG; + case WOLFSSL_EXPORT_VERSION_3: + WOLFSSL_MSG("Importing older version 3"); + optSz = DTLS_EXPORT_OPT_SZ_3; + break; + default: + WOLFSSL_MSG("Bad export version"); + ret = BAD_FUNC_ARG; + } } - if (DTLS_EXPORT_LEN + optSz + idx > sz) { + if (ret == 0 && (WOLFSSL_EXPORT_LEN + optSz + idx > sz)) { WOLFSSL_MSG("Import Options struct error"); - return BUFFER_E; + ret = BUFFER_E; } - ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; - if (length != optSz) { - WOLFSSL_MSG("Import Options struct error"); - return BUFFER_E; + + if (ret == 0) { + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (length != optSz) { + WOLFSSL_MSG("Import Options struct error"); + ret = BUFFER_E; + } } - if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) { - WOLFSSL_MSG("Import Options struct error"); - return ret; + + if (ret == 0) { + rc = ImportOptions(ssl, buf + idx, length, version, isTLS); + if (rc < 0) { + WOLFSSL_MSG("Import Options struct error"); + ret = rc; + } + else { + idx += length; + } } - idx += length; /* perform sanity checks and extract Keys struct */ - if (DTLS_EXPORT_LEN + idx > sz) { + if (ret == 0 && (WOLFSSL_EXPORT_LEN + idx > sz)) { WOLFSSL_MSG("Import Key struct error"); - return BUFFER_E; + ret = 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 == 0) { + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + ret = BUFFER_E; + } } - if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) { - WOLFSSL_MSG("Import Key struct error"); - return ret; + + if (ret == 0) { + rc = ImportKeyState(ssl, buf + idx, length, version, isTLS); + if (rc < 0) { + WOLFSSL_MSG("Import Key struct error"); + ret = rc; + } + else { + idx += rc; + } } - idx += ret; /* perform sanity checks and extract CipherSpecs struct */ - if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) { + if (ret == 0 && (WOLFSSL_EXPORT_LEN + WOLFSSL_EXPORT_SPC_SZ + idx > sz)) { WOLFSSL_MSG("Import CipherSpecs struct error"); - return BUFFER_E; + ret = BUFFER_E; } - ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; - if ( length != DTLS_EXPORT_SPC_SZ) { - WOLFSSL_MSG("Import CipherSpecs struct error"); - return BUFFER_E; + + if (ret == 0) { + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (length != WOLFSSL_EXPORT_SPC_SZ) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + ret = BUFFER_E; + } } - if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) { - WOLFSSL_MSG("Import CipherSpecs struct error"); - return ret; + + if (ret == 0) { + rc = ImportCipherSpecState(ssl, buf + idx, length, version, isTLS); + if (rc < 0) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + ret = rc; + } + else { + idx += rc; + } } - idx += ret; /* perform sanity checks and extract DTLS peer info */ - if (DTLS_EXPORT_LEN + idx > sz) { - WOLFSSL_MSG("Import DTLS peer info error"); - return BUFFER_E; - } - ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; - if (idx + length > sz) { - WOLFSSL_MSG("Import DTLS peer info error"); - return BUFFER_E; - } - if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) { - WOLFSSL_MSG("Import Peer Addr error"); - return ret; - } - idx += ret; + if (!isTLS) { + if (ret == 0 && (WOLFSSL_EXPORT_LEN + idx > sz)) { + WOLFSSL_MSG("Import DTLS peer info error"); + ret = BUFFER_E; + } + + if (ret == 0) { + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (idx + length > sz) { + WOLFSSL_MSG("Import DTLS peer info error"); + ret = BUFFER_E; + } + } + + #ifdef WOLFSSL_DTLS + if (ret == 0) { + rc = ImportPeerInfo(ssl, buf + idx, length, version); + if (rc < 0) { + WOLFSSL_MSG("Import Peer Addr error"); + ret = rc; + } + else { + idx += rc; + } + } + #endif + } - SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); /* make sure is a valid suite used */ - if (wolfSSL_get_cipher(ssl) == NULL) { + if (ret == 0 && wolfSSL_get_cipher(ssl) == NULL) { WOLFSSL_MSG("Can not match cipher suite imported"); - return MATCH_SUITE_ERROR; + ret = MATCH_SUITE_ERROR; } #ifndef WOLFSSL_AEAD_ONLY @@ -1710,16 +1800,151 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, const byte* buf, word32 sz) } /* do not allow stream ciphers with DTLS, except for NULL cipher */ - if (ssl->specs.cipher_type == stream && + if (ret == 0 && ssl->specs.cipher_type == stream && ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) { WOLFSSL_MSG("Can not import stream ciphers for DTLS"); - return SANITY_CIPHER_E; + ret = SANITY_CIPHER_E; } #endif /* !WOLFSSL_AEAD_ONLY */ + if (ret != 0) { + idx = ret; + } + WOLFSSL_LEAVE("wolfSSL_session_import_internal", idx); return idx; } -#endif /* WOLFSSL_DTLS */ + + +/** + * Handles serializing the session information. + * + * @param ssl WOLFSSL structure to serialize session from + * @param buf output buffer to hold serialized session + * @param sz the size of buffer 'buf', if too small then gets updated + * @param isTLS if the input WOLFSSL structure is expected to be TLS or DTLS + * 1 for yes is TLS and 0 for no is DTLS + * + * @return the size of serialized buffer on success and negative values on fail + */ +int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, + int isTLS) +{ + int ret = 0; + word32 idx = 0; + word32 totalLen = 0; + + WOLFSSL_ENTER("wolfSSL_session_export_internal"); + + if (buf == NULL || ssl == NULL) { + WOLFSSL_MSG("unexpected null argument"); + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + totalLen += WOLFSSL_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */ + /* each of the following have a 2 byte length before data */ + totalLen += WOLFSSL_EXPORT_LEN + DTLS_EXPORT_OPT_SZ; + totalLen += WOLFSSL_EXPORT_LEN + DTLS_EXPORT_KEY_SZ; + totalLen += WOLFSSL_EXPORT_LEN + WOLFSSL_EXPORT_SPC_SZ; + #ifdef WOLFSSL_DTLS + if (!isTLS) { + totalLen += WOLFSSL_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz; + } + #endif + } + + /* check is at least the minimum size needed, TLS cipher states add more */ + if (ret == 0 && totalLen > *sz) { + WOLFSSL_MSG("export buffer was too small"); + *sz = totalLen; + + /* possible AES state needed */ + if (isTLS) { + *sz += AES_BLOCK_SIZE*2; + } + ret = LENGTH_ONLY_E; + } + + if (ret == 0) { + buf[idx++] = (byte)(isTLS)? TLS_EXPORT_PRO : DTLS_EXPORT_PRO; + buf[idx++] = ((byte)((isTLS)? TLS_EXPORT_PRO : DTLS_EXPORT_PRO) & 0xF0) + | ((byte)WOLFSSL_EXPORT_VERSION & 0X0F); + + idx += WOLFSSL_EXPORT_LEN; /* leave spot for length */ + c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); + idx += WOLFSSL_EXPORT_LEN; + ret = ExportOptions(ssl, buf + idx, *sz - idx, WOLFSSL_EXPORT_VERSION, + isTLS); + if (ret >= 0) { + idx += ret; + ret = 0; + } + } + + /* export keys struct and dtls state -- variable length stored in ret */ + if (ret == 0) { + idx += WOLFSSL_EXPORT_LEN; /* leave room for length */ + ret = ExportKeyState(ssl, buf + idx, *sz - idx, WOLFSSL_EXPORT_VERSION, + 0, isTLS); + if (ret >= 0) { + c16toa((word16)ret, buf + idx - WOLFSSL_EXPORT_LEN); idx += ret; + ret = 0; + } + } + + /* export of cipher specs struct */ + if (ret == 0) { + c16toa((word16)WOLFSSL_EXPORT_SPC_SZ, buf + idx); + idx += WOLFSSL_EXPORT_LEN; + ret = ExportCipherSpecState(ssl, buf + idx, *sz - idx, + WOLFSSL_EXPORT_VERSION, isTLS); + if (ret >= 0) { + idx += ret; + ret = 0; + } + } + + /* export of dtls peer information */ +#ifdef WOLFSSL_DTLS + if (ret == 0 && !isTLS) { + idx += WOLFSSL_EXPORT_LEN; + #ifdef WOLFSSL_SESSION_EXPORT_NOPEER + ret = 0; /* not saving peer port/ip information */ + #else + ret = ExportPeerInfo(ssl, buf + idx, *sz - idx, WOLFSSL_EXPORT_VERSION); + #endif + if (ret >= 0) { + c16toa(ret, buf + idx - WOLFSSL_EXPORT_LEN); + idx += ret; + ret = 0; + } + } +#endif + + if (ret != 0) { + /*in a fail case clear the buffer which could contain partial key info*/ + XMEMSET(buf, 0, *sz); + } + + /* place total length of exported buffer minus 2 bytes protocol/version */ + if (ret == 0) { + c16toa((word16)(idx - WOLFSSL_EXPORT_LEN), buf + WOLFSSL_EXPORT_LEN); + ret = idx; + + #ifdef WOLFSSL_SESSION_EXPORT_DEBUG + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Exporting TLS session\n" + "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" + ,(int)WOLFSSL_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2); + WOLFSSL_MSG(debug); + } + #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + } + + WOLFSSL_LEAVE("wolfSSL_session_export_internal", ret); + return ret; +} #endif /* WOLFSSL_SESSION_EXPORT */ @@ -17671,6 +17896,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, if (ret != 0) goto exit_buildmsg; + XMEMSET(args->iv, 0, args->ivSz); } #if !defined(NO_PUBLIC_GCM_SET_IV) && \ ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ diff --git a/src/ssl.c b/src/ssl.c index cdbd8bb8b..9391974f8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -239,6 +239,45 @@ byte tsip_rootCAverified( ); #endif #ifdef WOLFSSL_SESSION_EXPORT +/** + * Used to import a serialized TLS session. In most cases wolfSSL_get_session + * should be used instead, this function is for exporting the state of the + * connection and when imported a resumption is not needed. + * WARNING: buf contains sensitive information about the state and is best to be + * encrypted before storing if stored. + * + * @param ssl WOLFSSL structure to import the session into + * @param buf serialized session + * @param sz size of buffer 'buf' + * @return the number of bytes read from buffer 'buf' + */ +int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) +{ + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS); +} + + +/** + * Used to export a serialized TLS session. In most cases wolfSSL_set_session + * should be used instead, this function is for importing a serialized state of + * the connection. + * + * @param ssl WOLFSSL structure to export the session from + * @param buf output of serialized session + * @param sz size in bytes set in 'buf' + * @return the number of bytes written into buffer 'buf' + */ +int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) +{ + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS); +} + #ifdef WOLFSSL_DTLS int wolfSSL_dtls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) { @@ -249,7 +288,7 @@ int wolfSSL_dtls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) } /* sanity checks on buffer and protocol are done in internal function */ - return wolfSSL_dtls_import_internal(ssl, buf, sz); + return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS); } @@ -319,7 +358,7 @@ int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) } /* copy over keys, options, and dtls state struct */ - return wolfSSL_dtls_export_internal(ssl, buf, *sz); + return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS); } @@ -363,7 +402,7 @@ int wolfSSL_send_session(WOLFSSL* ssl) { int ret; byte* buf; - word16 bufSz = MAX_EXPORT_BUFFER; + word32 bufSz = MAX_EXPORT_BUFFER; WOLFSSL_ENTER("wolfSSL_send_session"); @@ -384,7 +423,7 @@ int wolfSSL_send_session(WOLFSSL* ssl) } /* copy over keys, options, and dtls state struct */ - ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz); + ret = wolfSSL_session_export_internal(ssl, buf, &bufSz, WOLFSSL_EXPORT_DTLS); if (ret < 0) { XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; @@ -14247,7 +14286,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } #endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */ -#ifdef WOLFSSL_SESSION_EXPORT +#if defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS) if (ssl->dtls_export) { if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { WOLFSSL_MSG("Export DTLS session error"); diff --git a/tests/api.c b/tests/api.c index a77bb55f6..616ae4090 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3642,11 +3642,12 @@ static void test_wolfSSL_EVP_CIPHER_CTX(void) #ifdef HAVE_IO_TESTS_DEPENDENCIES #ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS /* set up function for sending session information */ static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx) { - WOLFSSL_CTX* ctx; - WOLFSSL* ssl; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; AssertNotNull(inSsl); AssertNotNull(buf); @@ -3666,6 +3667,7 @@ static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx) (void)userCtx; return WOLFSSL_SUCCESS; } +#endif /* returns negative value on fail and positive (including 0) on success */ static int nonblocking_accept_read(void* args, WOLFSSL* ssl, SOCKET_T* sockfd) @@ -4814,7 +4816,8 @@ done: /* SNI / ALPN / session export helper functions */ -#if defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLFSSL_SESSION_EXPORT) +#if defined(HAVE_SNI) || defined(HAVE_ALPN) ||\ + (defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS)) static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) { @@ -4854,7 +4857,7 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif -#ifdef WOLFSSL_SESSION_EXPORT +#if defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS) AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_dtls_set_export(ctx, test_export)); #endif @@ -4929,7 +4932,8 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) } AssertIntEQ(len, wolfSSL_write(ssl, msg, len)); -#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IO_POOL) +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IO_POOL) && \ + defined(WOLFSSL_DTLS) if (wolfSSL_dtls(ssl)) { byte* import; word32 sz; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 858c5c368..8d0d73739 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1323,23 +1323,29 @@ enum Misc { 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 */ + TLS_EXPORT_PRO = 167,/* wolfSSL protocol for serialized TLS */ DTLS_EXPORT_OPT_SZ = 61, /* amount of bytes used from Options */ - DTLS_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ DTLS_EXPORT_OPT_SZ_3 = 60, /* amount of bytes used from Options */ DTLS_EXPORT_KEY_SZ = 325 + (DTLS_SEQ_SZ * 2), /* max amount of bytes used from Keys */ DTLS_EXPORT_MIN_KEY_SZ = 85 + (DTLS_SEQ_SZ * 2), /* 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 */ + WOLFSSL_EXPORT_TLS = 1, + WOLFSSL_EXPORT_DTLS = 0, + WOLFSSL_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */ + WOLFSSL_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ + WOLFSSL_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ + + /* older export versions supported */ + WOLFSSL_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ + DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ DTLS_MTU_ADDITIONAL_READ_BUFFER = WOLFSSL_DTLS_MTU_ADDITIONAL_READ_BUFFER, /* Additional bytes to read so that * we can work with a peer that has * a slightly different MTU than us. */ MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ - MAX_EXPORT_STATE_BUFFER = (DTLS_EXPORT_MIN_KEY_SZ) + (3 * DTLS_EXPORT_LEN), + MAX_EXPORT_STATE_BUFFER = (DTLS_EXPORT_MIN_KEY_SZ) + (3 * WOLFSSL_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 */ @@ -1654,17 +1660,19 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); - #ifdef WOLFSSL_SESSION_EXPORT - WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, const byte* buf, - word32 sz); - WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, - word32 sz); +#endif +#ifdef WOLFSSL_SESSION_EXPORT +WOLFSSL_LOCAL int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, + word32* sz, int isTLS); +WOLFSSL_LOCAL int wolfSSL_session_import_internal(WOLFSSL* ssl, const byte* buf, + word32 sz, int isTLS); +#ifdef WOLFSSL_DTLS WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz); WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz); WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl); - #endif +#endif #endif struct WOLFSSL_BY_DIR_HASH { diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 44572de4c..83c99d875 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -878,6 +878,9 @@ WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); #endif #ifdef WOLFSSL_SESSION_EXPORT +int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz); +int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz); + #ifdef WOLFSSL_DTLS #ifndef WOLFSSL_DTLS_EXPORT_TYPES From 22b6cc675a6dcae891dd59d53320816a665ba2c5 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 24 May 2021 23:04:59 +0700 Subject: [PATCH 02/13] add import/export of peer info with tls --- src/internal.c | 72 +++++++++++++++++++++---------------------- src/wolfio.c | 77 ++++++++++++++++++++++++++++++++++++---------- wolfssl/internal.h | 7 +++-- wolfssl/wolfio.h | 28 ++++++++--------- 4 files changed, 114 insertions(+), 70 deletions(-) diff --git a/src/internal.c b/src/internal.c index 4c5af8058..8773a7cd1 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1370,15 +1370,14 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, } -#ifdef WOLFSSL_DTLS #ifndef WOLFSSL_SESSION_EXPORT_NOPEER static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) { int idx = 0; - int ipSz = DTLS_EXPORT_IP; /* start as max size */ + int ipSz = MAX_EXPORT_IP; /* start as max size */ int fam = 0; word16 port = 0; - char ip[DTLS_EXPORT_IP]; + char ip[MAX_EXPORT_IP]; if (ver != WOLFSSL_EXPORT_VERSION) { WOLFSSL_MSG("Export version not supported"); @@ -1399,7 +1398,7 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) } /* check that ipSz/fam is not negative or too large since user can set cb */ - if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) { + if (ipSz < 0 || ipSz > MAX_EXPORT_IP || fam < 0) { WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback"); return SOCKET_ERROR_E; } @@ -1420,7 +1419,7 @@ static int ImportPeerInfo(WOLFSSL* ssl, const byte* buf, word32 len, byte ver) word16 ipSz; word16 fam; word16 port; - char ip[DTLS_EXPORT_IP]; + char ip[MAX_EXPORT_IP]; if (ver != WOLFSSL_EXPORT_VERSION && ver != WOLFSSL_EXPORT_VERSION_3) { WOLFSSL_MSG("Export version not supported"); @@ -1463,6 +1462,7 @@ static int ImportPeerInfo(WOLFSSL* ssl, const byte* buf, word32 len, byte ver) } +#ifdef WOLFSSL_DTLS /* 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. @@ -1669,7 +1669,12 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, if (ret == 0) { switch (version) { case WOLFSSL_EXPORT_VERSION: - optSz = DTLS_EXPORT_OPT_SZ; + if (!isTLS) { + optSz = DTLS_EXPORT_OPT_SZ; + } + else { + optSz = TLS_EXPORT_OPT_SZ; + } break; case WOLFSSL_EXPORT_VERSION_3: @@ -1758,32 +1763,28 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, } /* perform sanity checks and extract DTLS peer info */ - if (!isTLS) { - if (ret == 0 && (WOLFSSL_EXPORT_LEN + idx > sz)) { + if (ret == 0 && (WOLFSSL_EXPORT_LEN + idx > sz)) { + WOLFSSL_MSG("Import DTLS peer info error"); + ret = BUFFER_E; + } + + if (ret == 0) { + ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; + if (idx + length > sz) { WOLFSSL_MSG("Import DTLS peer info error"); ret = BUFFER_E; } + } - if (ret == 0) { - ato16(buf + idx, &length); idx += WOLFSSL_EXPORT_LEN; - if (idx + length > sz) { - WOLFSSL_MSG("Import DTLS peer info error"); - ret = BUFFER_E; - } + if (ret == 0) { + rc = ImportPeerInfo(ssl, buf + idx, length, version); + if (rc < 0) { + WOLFSSL_MSG("Import Peer Addr error"); + ret = rc; } - - #ifdef WOLFSSL_DTLS - if (ret == 0) { - rc = ImportPeerInfo(ssl, buf + idx, length, version); - if (rc < 0) { - WOLFSSL_MSG("Import Peer Addr error"); - ret = rc; - } - else { - idx += rc; - } + else { + idx += rc; } - #endif } /* make sure is a valid suite used */ @@ -1870,12 +1871,13 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, buf[idx++] = ((byte)((isTLS)? TLS_EXPORT_PRO : DTLS_EXPORT_PRO) & 0xF0) | ((byte)WOLFSSL_EXPORT_VERSION & 0X0F); - idx += WOLFSSL_EXPORT_LEN; /* leave spot for length */ - c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); + idx += WOLFSSL_EXPORT_LEN; /* leave spot for length of total buffer */ + idx += WOLFSSL_EXPORT_LEN; ret = ExportOptions(ssl, buf + idx, *sz - idx, WOLFSSL_EXPORT_VERSION, isTLS); if (ret >= 0) { + c16toa((word16)ret, buf + idx - WOLFSSL_EXPORT_LEN); idx += ret; ret = 0; } @@ -1904,9 +1906,8 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, } } - /* export of dtls peer information */ -#ifdef WOLFSSL_DTLS - if (ret == 0 && !isTLS) { + /* export of peer information */ + if (ret == 0) { idx += WOLFSSL_EXPORT_LEN; #ifdef WOLFSSL_SESSION_EXPORT_NOPEER ret = 0; /* not saving peer port/ip information */ @@ -1919,7 +1920,6 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, ret = 0; } } -#endif if (ret != 0) { /*in a fail case clear the buffer which could contain partial key info*/ @@ -2071,15 +2071,15 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #else ctx->CBIORecv = EmbedReceive; ctx->CBIOSend = EmbedSend; + #ifdef WOLFSSL_SESSION_EXPORT + ctx->CBGetPeer = EmbedGetPeer; + ctx->CBSetPeer = EmbedSetPeer; + #endif #ifdef WOLFSSL_DTLS if (method->version.major == DTLS_MAJOR) { ctx->CBIORecv = EmbedReceiveFrom; ctx->CBIOSend = EmbedSendTo; } - #ifdef WOLFSSL_SESSION_EXPORT - ctx->CBGetPeer = EmbedGetPeer; - ctx->CBSetPeer = EmbedSetPeer; - #endif #endif #endif /* MICRIUM */ #endif /* WOLFSSL_USER_IO */ diff --git a/src/wolfio.c b/src/wolfio.c index 23afcb812..020c3dc21 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -477,25 +477,18 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) return sz; } +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_SESSION_EXPORT - /* get the peer information in human readable form (ip, port, family) - * default function assumes BSD sockets - * can be overridden with wolfSSL_CTX_SetIOGetPeer - */ - int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, +#ifdef WOLFSSL_DTLS + static int EmbedGetPeerDTLS(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)) @@ -536,11 +529,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) return WOLFSSL_SUCCESS; } - /* set the peer information in human readable form (ip, port, family) - * default function assumes BSD sockets - * can be overridden with wolfSSL_CTX_SetIOSetPeer - */ - int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + static int EmbedSetPeerDTLS(WOLFSSL* ssl, char* ip, int ipSz, unsigned short port, int fam) { int ret; @@ -594,8 +583,62 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) return WOLFSSL_SUCCESS; } +#endif + + /* get the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overridden with wolfSSL_CTX_SetIOGetPeer + */ + int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam) + { + if (ssl == NULL || ip == NULL || ipSz == NULL || + port == NULL || fam == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + return EmbedGetPeerDTLS(ssl, ip, ipSz, port, fam); + #else + return NOT_COMPILED_IN; + #endif + } + else { + *port = wolfSSL_get_fd(ssl); + ip[0] = '\0'; + *ipSz = 0; + *fam = 0; + return WOLFSSL_SUCCESS; + } + } + + /* set the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overridden with wolfSSL_CTX_SetIOSetPeer + */ + int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam) + { + /* sanity checks on arguments */ + if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) { + return BAD_FUNC_ARG; + } + + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + return EmbedSetPeerDTLS(ssl, ip, ipSz, port, fam); + #else + return NOT_COMPILED_IN; + #endif + } + else { + wolfSSL_set_fd(ssl, port); + (void)fam; + return WOLFSSL_SUCCESS; + } + } #endif /* WOLFSSL_SESSION_EXPORT */ -#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_LINUXKM static int linuxkm_send(struct socket *socket, void *buf, int size, @@ -1772,6 +1815,7 @@ void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) return NULL; } +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_SESSION_EXPORT @@ -1789,7 +1833,6 @@ void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) } #endif /* WOLFSSL_SESSION_EXPORT */ -#endif /* WOLFSSL_DTLS */ #ifdef HAVE_NETX diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 8d0d73739..55cb14556 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1325,6 +1325,7 @@ enum Misc { DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */ TLS_EXPORT_PRO = 167,/* wolfSSL protocol for serialized TLS */ DTLS_EXPORT_OPT_SZ = 61, /* amount of bytes used from Options */ + TLS_EXPORT_OPT_SZ = 65, /* amount of bytes used from Options */ DTLS_EXPORT_OPT_SZ_3 = 60, /* amount of bytes used from Options */ DTLS_EXPORT_KEY_SZ = 325 + (DTLS_SEQ_SZ * 2), /* max amount of bytes used from Keys */ @@ -1339,7 +1340,7 @@ enum Misc { /* older export versions supported */ WOLFSSL_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ - DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ + MAX_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ DTLS_MTU_ADDITIONAL_READ_BUFFER = WOLFSSL_DTLS_MTU_ADDITIONAL_READ_BUFFER, /* Additional bytes to read so that * we can work with a peer that has @@ -2852,12 +2853,14 @@ struct WOLFSSL_CTX { CallbackIOSend CBIOSend; #ifdef WOLFSSL_DTLS CallbackGenCookie CBIOCookie; /* gen cookie callback */ +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS wc_dtls_export dtls_export; /* export function for DTLS session */ +#endif CallbackGetPeer CBGetPeer; CallbackSetPeer CBSetPeer; #endif -#endif /* WOLFSSL_DTLS */ VerifyCallback verifyCallback; /* cert verification callback */ #ifdef OPENSSL_ALL CertVerifyCallback verifyCertCb; diff --git a/wolfssl/wolfio.h b/wolfssl/wolfio.h index a6363f5cf..9e1f76f4a 100644 --- a/wolfssl/wolfio.h +++ b/wolfssl/wolfio.h @@ -429,12 +429,6 @@ WOLFSSL_API int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL* ssl, char* buf, int sz, void*); #endif /* WOLFSSL_MULTICAST */ - #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); - #endif /* WOLFSSL_SESSION_EXPORT */ #endif /* WOLFSSL_DTLS */ #endif /* USE_WOLFSSL_IO */ @@ -593,16 +587,20 @@ WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); - #ifdef WOLFSSL_SESSION_EXPORT - 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 +#ifdef WOLFSSL_SESSION_EXPORT + 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); + 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); +#endif /* WOLFSSL_SESSION_EXPORT */ From 64f53c4e1b51844bffde63932e47bef18f2f6616 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 26 May 2021 18:30:22 +0700 Subject: [PATCH 03/13] fix macro name and make api public --- src/wolfio.c | 2 +- wolfssl/ssl.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/wolfio.c b/src/wolfio.c index 020c3dc21..4c7efad88 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -536,7 +536,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) SOCKADDR_S addr; /* sanity checks on arguments */ - if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) { + if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) { return BAD_FUNC_ARG; } diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 83c99d875..7b3f0b7d5 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -878,8 +878,10 @@ WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); #endif #ifdef WOLFSSL_SESSION_EXPORT -int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz); -int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz); +WOLFSSL_API int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, + unsigned int sz); +WOLFSSL_API int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); #ifdef WOLFSSL_DTLS From 1929024029d3d789e7daa094d5d599c3d87e43a0 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Sat, 29 May 2021 01:10:30 +0700 Subject: [PATCH 04/13] fix for getting export buffer size --- src/internal.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/internal.c b/src/internal.c index 8773a7cd1..9c3049c76 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1836,7 +1836,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, WOLFSSL_ENTER("wolfSSL_session_export_internal"); - if (buf == NULL || ssl == NULL) { + if (ssl == NULL) { WOLFSSL_MSG("unexpected null argument"); ret = BAD_FUNC_ARG; } @@ -1855,8 +1855,8 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, } /* check is at least the minimum size needed, TLS cipher states add more */ - if (ret == 0 && totalLen > *sz) { - WOLFSSL_MSG("export buffer was too small"); + if (ret == 0 && (totalLen > *sz || buf == NULL)) { + WOLFSSL_MSG("export buffer was too small or null"); *sz = totalLen; /* possible AES state needed */ @@ -1921,7 +1921,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, } } - if (ret != 0) { + if (ret != 0 && buf != NULL) { /*in a fail case clear the buffer which could contain partial key info*/ XMEMSET(buf, 0, *sz); } @@ -1942,6 +1942,10 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ } + if (ret >= 0) { + *sz = ret; + } + WOLFSSL_LEAVE("wolfSSL_session_export_internal", ret); return ret; } From 8b456b90e037e87c0a4e2a1f5d401bab34a81084 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 1 Jun 2021 15:45:45 +0700 Subject: [PATCH 05/13] add test case for tls export/import --- src/internal.c | 1 + tests/api.c | 301 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+) diff --git a/src/internal.c b/src/internal.c index 9c3049c76..fea5f5023 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1640,6 +1640,7 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, /* check if importing state only */ return wolfSSL_dtls_import_state_internal(ssl, buf, sz); #else + WOLFSSL_MSG("Invalid serialized session protocol value"); ret = BAD_FUNC_ARG; #endif } diff --git a/tests/api.c b/tests/api.c index 616ae4090..46ef4fa0f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5649,6 +5649,306 @@ static void test_wolfSSL_dtls_export(void) #endif } + +#if defined(WOLFSSL_SESSION_EXPORT) +static byte canned_client_session[] = { + 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0x27, 0x0A, 0x0D, 0x10, 0x01, 0x01, 0x0A, 0x00, + 0x05, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x0A, 0x01, 0x01, 0x00, 0x20, 0x69, 0x11, 0x6D, + 0x97, 0x15, 0x6E, 0x52, 0x27, 0xD6, 0x1D, 0x1D, + 0xF5, 0x0D, 0x59, 0xA5, 0xAC, 0x2E, 0x8C, 0x0E, + 0xCB, 0x26, 0x1E, 0xE2, 0xCE, 0xBB, 0xCE, 0xE1, + 0x7D, 0xD7, 0xEF, 0xA5, 0x44, 0x80, 0x2A, 0xDE, + 0xBB, 0x75, 0xB0, 0x1D, 0x75, 0x17, 0x20, 0x4C, + 0x08, 0x05, 0x1B, 0xBA, 0x60, 0x1F, 0x6C, 0x91, + 0x8C, 0xAA, 0xBB, 0xE5, 0xA3, 0x0B, 0x12, 0x3E, + 0xC0, 0x35, 0x43, 0x1D, 0xE2, 0x10, 0xE2, 0x02, + 0x92, 0x4B, 0x8F, 0x05, 0xA9, 0x4B, 0xCC, 0x90, + 0xC3, 0x0E, 0xC2, 0x0F, 0xE9, 0x33, 0x85, 0x9B, + 0x3C, 0x19, 0x21, 0xD5, 0x62, 0xE5, 0xE1, 0x17, + 0x8F, 0x8C, 0x19, 0x52, 0xD8, 0x59, 0x10, 0x2D, + 0x20, 0x6F, 0xBA, 0xC1, 0x1C, 0xD1, 0x82, 0xC7, + 0x32, 0x1B, 0xBB, 0xCC, 0x30, 0x03, 0xD7, 0x3A, + 0xC8, 0x18, 0xED, 0x58, 0xC8, 0x11, 0xFE, 0x71, + 0x9C, 0x71, 0xD8, 0x6B, 0xE0, 0x25, 0x64, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, + 0x00, 0x00, 0x06, 0x01, 0x04, 0x08, 0x01, 0x20, + 0x28, 0x00, 0x09, 0xE1, 0x50, 0x70, 0x02, 0x2F, + 0x7E, 0xDA, 0xBD, 0x40, 0xC5, 0x58, 0x87, 0xCE, + 0x43, 0xF3, 0xC5, 0x8F, 0xA1, 0x59, 0x93, 0xEF, + 0x7E, 0xD3, 0xD0, 0xB5, 0x87, 0x1D, 0x81, 0x54, + 0x14, 0x63, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03 +}; + + +static byte canned_server_session[] = { + 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0x27, 0x08, 0x0F, 0x10, 0x01, 0x01, 0x00, 0x11, + 0x05, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x0A, 0x01, 0x01, 0x00, 0x20, 0x69, 0x11, 0x6D, + 0x97, 0x15, 0x6E, 0x52, 0x27, 0xD6, 0x1D, 0x1D, + 0xF5, 0x0D, 0x59, 0xA5, 0xAC, 0x2E, 0x8C, 0x0E, + 0xCB, 0x26, 0x1E, 0xE2, 0xCE, 0xBB, 0xCE, 0xE1, + 0x7D, 0xD7, 0xEF, 0xA5, 0x44, 0x80, 0x2A, 0xDE, + 0xBB, 0x75, 0xB0, 0x1D, 0x75, 0x17, 0x20, 0x4C, + 0x08, 0x05, 0x1B, 0xBA, 0x60, 0x1F, 0x6C, 0x91, + 0x8C, 0xAA, 0xBB, 0xE5, 0xA3, 0x0B, 0x12, 0x3E, + 0xC0, 0x35, 0x43, 0x1D, 0xE2, 0x10, 0xE2, 0x02, + 0x92, 0x4B, 0x8F, 0x05, 0xA9, 0x4B, 0xCC, 0x90, + 0xC3, 0x0E, 0xC2, 0x0F, 0xE9, 0x33, 0x85, 0x9B, + 0x3C, 0x19, 0x21, 0xD5, 0x62, 0xE5, 0xE1, 0x17, + 0x8F, 0x8C, 0x19, 0x52, 0xD8, 0x59, 0x10, 0x2D, + 0x20, 0x6F, 0xBA, 0xC1, 0x1C, 0xD1, 0x82, 0xC7, + 0x32, 0x1B, 0xBB, 0xCC, 0x30, 0x03, 0xD7, 0x3A, + 0xC8, 0x18, 0xED, 0x58, 0xC8, 0x11, 0xFE, 0x71, + 0x9C, 0x71, 0xD8, 0x6B, 0xE0, 0x25, 0x64, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, + 0x00, 0x00, 0x06, 0x01, 0x04, 0x08, 0x01, 0x20, + 0x28, 0x00, 0xC5, 0x8F, 0xA1, 0x59, 0x93, 0xEF, + 0x7E, 0xD3, 0xD0, 0xB5, 0x87, 0x1D, 0x81, 0x54, + 0x14, 0x63, 0x09, 0xE1, 0x50, 0x70, 0x02, 0x2F, + 0x7E, 0xDA, 0xBD, 0x40, 0xC5, 0x58, 0x87, 0xCE, + 0x43, 0xF3, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04 +}; + + +static THREAD_RETURN WOLFSSL_THREAD tls_export_server(void* args) +{ + SOCKET_T sockfd = 0; + SOCKET_T clientfd = 0; + word16 port; + + callback_functions* cbf; + WOLFSSL_CTX* ctx = 0; + WOLFSSL* ssl = 0; + + char msg[] = "I hear you fa shizzle!"; + char input[1024]; + int idx; + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + ((func_args*)args)->return_code = TEST_FAIL; + cbf = ((func_args*)args)->callbacks; + + { + WOLFSSL_METHOD* method = NULL; + if (cbf != NULL && cbf->method != NULL) { + method = cbf->method(); + } + else { + method = wolfTLSv1_2_server_method(); + } + ctx = wolfSSL_CTX_new(method); + } + if (ctx == NULL) { + goto done; + } + wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256"); + +#if defined(USE_WINDOWS_API) + port = ((func_args*)args)->signal->port; +#elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ + !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) + /* Let tcp_listen assign port */ + port = 0; +#else + /* Use default port */ + port = wolfSSLPort; +#endif + + /* do it here to detect failure */ + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); + CloseSocket(sockfd); + + /* call ctx setup callback */ + if (cbf != NULL && cbf->ctx_ready != NULL) { + cbf->ctx_ready(ctx); + } + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + goto done; + } + + /* call ssl setup callback */ + if (cbf != NULL && cbf->ssl_ready != NULL) { + cbf->ssl_ready(ssl); + } + AssertIntEQ(wolfSSL_tls_import(ssl, canned_server_session, + sizeof(canned_server_session)), sizeof(canned_server_session)); + wolfSSL_set_fd(ssl, clientfd); + + idx = wolfSSL_read(ssl, input, sizeof(input)-1); + if (idx > 0) { + input[idx] = '\0'; + printf("Client message export/import: %s\n", input); + } + else { + printf("ret = %d error = %d\n", idx, wolfSSL_get_error(ssl, idx)); + goto done; + } + + if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) { + /*err_sys("SSL_write failed");*/ +#ifdef WOLFSSL_TIRTOS + return; +#else + return 0; +#endif + } + +#ifdef WOLFSSL_TIRTOS + Task_yield(); +#endif + + ((func_args*)args)->return_code = TEST_SUCCESS; + +done: + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + CloseSocket(clientfd); + +#ifdef WOLFSSL_TIRTOS + fdCloseSession(Task_self()); +#endif + +#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ + && defined(HAVE_THREAD_LS) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + +#if defined(HAVE_SESSION_TICKET) && \ + ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) +#if defined(OPENSSL_EXTRA) && defined(HAVE_AESGCM) + OpenSSLTicketCleanup(); +#elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) + TicketCleanup(); +#endif +#endif + +#ifndef WOLFSSL_TIRTOS + return 0; +#endif +} +#endif + +static void test_wolfSSL_tls_export(void) +{ +#if defined(WOLFSSL_SESSION_EXPORT) + SOCKET_T sockfd = 0; + WOLFSSL_CTX* ctx = 0; + WOLFSSL* ssl = 0; + char msg[64] = "hello wolfssl!"; + char reply[1024]; + word32 replySz; + int msgSz = (int)XSTRLEN(msg); + + tcp_ready ready; + func_args server_args; + THREAD_TYPE serverThread; + callback_functions server_cbf; + + printf(testingFmt, "wolfSSL_tls_export()"); +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&server_cbf, 0, sizeof(callback_functions)); + server_cbf.method = wolfTLSv1_2_server_method; + server_args.callbacks = &server_cbf; + server_args.signal = &ready; + + start_thread(tls_export_server, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); + wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256"); + AssertNotNull(ssl = wolfSSL_new(ctx)); + tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl); + AssertIntEQ(wolfSSL_tls_import(ssl, canned_client_session, + sizeof(canned_client_session)), sizeof(canned_client_session)); + replySz = sizeof(reply); + AssertIntGT(wolfSSL_tls_export(ssl, (byte*)reply, &replySz), 0); + AssertIntEQ(XMEMCMP(reply, canned_client_session, replySz), 0); + wolfSSL_set_fd(ssl, sockfd); + + AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); + AssertIntGT(wolfSSL_read(ssl, reply, sizeof(reply)-1), 0); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + CloseSocket(sockfd); + +#ifdef WOLFSSL_TIRTOS + fdCloseSession(Task_self()); +#endif + +#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ + && defined(HAVE_THREAD_LS) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + + join_thread(serverThread); + + AssertIntEQ(server_args.return_code, TEST_SUCCESS); + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); +#endif +} + /*----------------------------------------------------------------------------* | TLS extensions tests *----------------------------------------------------------------------------*/ @@ -49187,6 +49487,7 @@ void ApiTest(void) #endif test_wolfSSL_CTX_verifyDepth_ServerClient(); test_wolfSSL_dtls_export(); + test_wolfSSL_tls_export(); #endif AssertIntEQ(test_wolfSSL_SetMinVersion(), WOLFSSL_SUCCESS); AssertIntEQ(test_wolfSSL_CTX_SetMinVersion(), WOLFSSL_SUCCESS); From 13478a94a80fbbab6c4eba582c70f677ea02680b Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 7 Jun 2021 23:28:14 +0700 Subject: [PATCH 06/13] sanity check on block size with block cipher type --- src/internal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/internal.c b/src/internal.c index fea5f5023..1bd033218 100644 --- a/src/internal.c +++ b/src/internal.c @@ -17850,6 +17850,12 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #ifndef WOLFSSL_AEAD_ONLY if (ssl->specs.cipher_type == block) { word32 blockSz = ssl->specs.block_size; + + if (blockSz == 0) { + WOLFSSL_MSG("Invalid block size with block cipher type"); + ERROR_OUT(BAD_STATE_E, exit_buildmsg); + } + if (ssl->options.tls1_1) { args->ivSz = blockSz; args->sz += args->ivSz; From 21181f2437459dd4491ca81031d4515655256106 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 7 Jun 2021 23:31:48 +0700 Subject: [PATCH 07/13] canned test was made without the wolfssl_idea enum on --- tests/api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/api.c b/tests/api.c index 46ef4fa0f..238f5cd74 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5650,7 +5650,7 @@ static void test_wolfSSL_dtls_export(void) } -#if defined(WOLFSSL_SESSION_EXPORT) +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) static byte canned_client_session[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, @@ -5868,7 +5868,7 @@ done: static void test_wolfSSL_tls_export(void) { -#if defined(WOLFSSL_SESSION_EXPORT) +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; From 41f3a006acb00db40b3b821b30836c2e1aeed8ba Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 8 Jun 2021 00:37:31 +0700 Subject: [PATCH 08/13] sanity check on padding size imported --- src/internal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/internal.c b/src/internal.c index 1bd033218..c6d83d7e6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -855,6 +855,11 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, specs->pad_size = exp[idx++]; specs->static_ecdh = exp[idx++]; + if (specs->pad_size != PAD_MD5 && specs->pad_size != PAD_SHA) { + WOLFSSL_MSG("Importing bad or unknown pad size"); + return BAD_STATE_E; + } + /* temporarly save the sequence numbers */ tmp_seq_peer_lo = ssl->keys.peer_sequence_number_lo; tmp_seq_peer_hi = ssl->keys.peer_sequence_number_hi; From 6e7c6e8a66bdb817633839d198bc6d3b102e8310 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 8 Jun 2021 01:23:53 +0700 Subject: [PATCH 09/13] add comments to dox header file --- doc/dox_comments/header_files/ssl.h | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index d49fba1d5..4194b61e7 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -568,6 +568,26 @@ WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int); WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz); + +/*! + \brief Used to import a serialized TLS session. In most cases + wolfSSL_get_session should be used instead, this function is for exporting + the state of the connection and when imported a resumption is not needed. + WARNING: buf contains sensitive information about the state and is best to + be encrypted before storing if stored. + + \return the number of bytes read from buffer 'buf' + + \param ssl WOLFSSL structure to import the session into + \param buf serialized session + \param sz size of buffer 'buf' + + \sa wolfSSL_dtls_import + \sa wolfSSL_tls_export + */ +WOLFSSL_API int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, + unsigned int sz); + /*! \brief The wolfSSL_CTX_dtls_set_export() function is used to set the callback function for exporting a session. It is allowed to @@ -680,6 +700,23 @@ 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); +/*! + \brief Used to export a serialized TLS session. In most cases + wolfSSL_set_session should be used instead, this function is for importing a + serialized state of the connection. + + \return the number of bytes written into buffer 'buf' + + \param ssl WOLFSSL structure to export the session from + \param buf output of serialized session + \param sz size in bytes set in 'buf' + + \sa wolfSSL_dtls_import + \sa wolfSSL_tls_import + */ +WOLFSSL_API int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); + /*! \brief This function is used to set aside static memory for a CTX. Memory set aside is then used for the CTX’s lifetime and for any SSL objects From ae47cb3bcda5076686d9960dcf99e78221bcd32f Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 28 Sep 2021 16:57:30 -0600 Subject: [PATCH 10/13] update check on is TLS, update macro guard for test case --- doc/dox_comments/header_files/ssl.h | 9 +- src/internal.c | 130 +++++++++++++++------------- tests/api.c | 10 ++- wolfssl/internal.h | 2 + 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 4194b61e7..f5b8a8512 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -570,11 +570,12 @@ WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, /*! - \brief Used to import a serialized TLS session. In most cases - wolfSSL_get_session should be used instead, this function is for exporting - the state of the connection and when imported a resumption is not needed. + \brief Used to import a serialized TLS session. This function is for + importing the state of the connection. WARNING: buf contains sensitive information about the state and is best to be encrypted before storing if stored. + Additional debug info can be displayed with the macro + WOLFSSL_SESSION_EXPORT_DEBUG defined. \return the number of bytes read from buffer 'buf' @@ -704,6 +705,8 @@ WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, \brief Used to export a serialized TLS session. In most cases wolfSSL_set_session should be used instead, this function is for importing a serialized state of the connection. + Additional debug info can be displayed with the macro + WOLFSSL_SESSION_EXPORT_DEBUG defined. \return the number of bytes written into buffer 'buf' diff --git a/src/internal.c b/src/internal.c index c6d83d7e6..7447d904a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -590,7 +590,7 @@ static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) * @return the amount written to 'exp' buffer */ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, - int isTLS) + int type) { word32 idx = 0; CipherSpecs* specs; @@ -601,8 +601,7 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, return BAD_FUNC_ARG; } - specs= &(ssl->specs); - + specs= &ssl->specs; if (WOLFSSL_EXPORT_SPC_SZ > len) { return BUFFER_E; } @@ -628,7 +627,8 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, } /* send over state of AES too */ - if (isTLS && ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { + if (type == WOLFSSL_EXPORT_TLS && + ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { byte *pt = (byte*)ssl->encrypt.aes->reg; if ((idx + 2*AES_BLOCK_SIZE) > len) { @@ -651,7 +651,7 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, /* serializes the key struct for exporting */ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, - byte small, int isTLS) + byte small, int type) { word32 idx = 0; byte sz; @@ -678,37 +678,40 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; #if defined(WOLFSSL_DTLS) - if (!isTLS) { - c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN; - c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN; - c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; + if (type == WOLFSSL_EXPORT_DTLS) { + c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN; - c16toa(keys->dtls_expected_peer_handshake_number, exp + idx); - idx += OPAQUE16_LEN; + c16toa(keys->dtls_peer_handshake_number, exp + idx); + idx += OPAQUE16_LEN; + c16toa(keys->dtls_expected_peer_handshake_number, exp + idx); + idx += OPAQUE16_LEN; - c16toa(keys->dtls_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->dtls_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN; - c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->dtls_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->dtls_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); + idx += OPAQUE16_LEN; + c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); + idx += OPAQUE32_LEN; + c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN; } #endif - c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN; - c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN; exp[idx++] = keys->encryptionOn; exp[idx++] = keys->decryptedCur; /* from here on the buffer needs checked because is variable length that * can be larger than DTLS_EXPORT_MIN_KEY_SZ */ #ifdef WOLFSSL_DTLS - if (!isTLS) { + if (type == WOLFSSL_EXPORT_DTLS) { word32 i; if ((OPAQUE16_LEN * 2) + idx + (2 * (WOLFSSL_DTLS_WINDOW_WORDS * OPAQUE32_LEN)) > len) { @@ -804,7 +807,7 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, WOLFSSL_LEAVE("ExportKeyState", idx); (void)ver; - (void)isTLS; + (void)type; return idx; } @@ -815,12 +818,12 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, * @param exp input buffer to read from * @param len length of exp buffer * @param ver version of import buffer found - * @param isTLS flag for importing a TLS session or DTLS + * @param type flag for importing a TLS session or DTLS * * @return size of exp buffer consumed on success and negative value on fail */ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, - byte ver, int isTLS) + byte ver, int type) { word32 idx = 0; CipherSpecs* specs; @@ -860,7 +863,7 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, return BAD_STATE_E; } - /* temporarly save the sequence numbers */ + /* temporarily save the sequence numbers */ tmp_seq_peer_lo = ssl->keys.peer_sequence_number_lo; tmp_seq_peer_hi = ssl->keys.peer_sequence_number_hi; tmp_seq_lo = ssl->keys.sequence_number_lo; @@ -874,7 +877,8 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, ssl->keys.sequence_number_lo = tmp_seq_lo; ssl->keys.sequence_number_hi = tmp_seq_hi; - if (isTLS && ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { + if (type == WOLFSSL_EXPORT_TLS && + ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { byte *pt = (byte*)ssl->encrypt.aes->reg; XMEMCPY(pt, exp + idx, AES_BLOCK_SIZE); idx += AES_BLOCK_SIZE; @@ -897,12 +901,12 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len, * @param exp buffer to read Key values from * @param len max length of buffer 'exp' * @param ver version of import buffer found - * @param isTLS flag for TLS vs DTLS + * @param type flag for TLS vs DTLS * * @return amount of data read from exp on success or negative on fail */ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, - int isTLS) + int type) { word32 idx = 0; byte sz; @@ -927,7 +931,7 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN; #if defined(WOLFSSL_DTLS) - if (!isTLS) { + if (type == WOLFSSL_EXPORT_DTLS) { ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN; ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN; ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN; @@ -958,7 +962,7 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, keys->decryptedCur = exp[idx++]; #if defined(WOLFSSL_DTLS) - if (!isTLS) { + if (type == WOLFSSL_EXPORT_DTLS) { word16 i, wordCount, wordAdj = 0; /* do window */ @@ -1052,7 +1056,7 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, WOLFSSL_LEAVE("ImportKeyState", idx); (void)ver; - (void)isTLS; + (void)type; return idx; } @@ -1060,7 +1064,7 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, /* copy over necessary information from Options struct to buffer * On success returns size of buffer used on failure returns a negative value */ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, - int isTLS) + int type) { int idx = 0; word16 zero = 0; @@ -1181,7 +1185,7 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, exp[idx++] = options->acceptState; exp[idx++] = options->asyncState; - if (isTLS) { + if (type == WOLFSSL_EXPORT_TLS) { exp[idx++] = ssl->options.disallowEncThenMac; exp[idx++] = ssl->options.encThenMac; exp[idx++] = ssl->options.startedETMRead; @@ -1204,7 +1208,7 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, break; case WOLFSSL_EXPORT_VERSION: - if (idx != DTLS_EXPORT_OPT_SZ && !isTLS) { + if (idx != DTLS_EXPORT_OPT_SZ && type == WOLFSSL_EXPORT_DTLS) { WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); return DTLS_EXPORT_VER_E; } @@ -1217,7 +1221,7 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, WOLFSSL_LEAVE("ExportOptions", idx); - (void)isTLS; + (void)type; return idx; } @@ -1225,7 +1229,7 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, /* copy items from Export struct to Options struct * On success returns size of buffer used on failure returns a negative value */ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, - int isTLS) + int type) { int idx = 0; Options* options = &ssl->options; @@ -1357,7 +1361,7 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, options->acceptState = exp[idx++]; options->asyncState = exp[idx++]; - if (isTLS) { + if (type == WOLFSSL_EXPORT_TLS) { ssl->options.disallowEncThenMac = exp[idx++]; ssl->options.encThenMac = exp[idx++]; ssl->options.startedETMRead = exp[idx++]; @@ -1370,7 +1374,6 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, return VERSION_ERROR; } - (void)isTLS; return idx; } @@ -1389,7 +1392,8 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) return BAD_FUNC_ARG; } - if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * WOLFSSL_EXPORT_LEN) { + if (ssl == NULL || exp == NULL || + len < (sizeof(ip) + 3 * WOLFSSL_EXPORT_LEN)) { return BAD_FUNC_ARG; } @@ -1516,7 +1520,7 @@ int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) 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); + , (int)WOLFSSL_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2); WOLFSSL_MSG(debug); } #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ @@ -1606,16 +1610,16 @@ int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, const byte* buf, word32 sz) * @param ssl WOLFSSL structure to import into * @param buf buffer containing serialized session * @param sz size of buffer 'buf' - * @param isTLS flag for TLS or DTLS + * @param type flag for TLS or DTLS * * @return the size of serialized buffer on success */ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, - unsigned int sz, int isTLS) + unsigned int sz, int type) { word32 idx = 0; word16 length = 0; - int version; + int version = 0; int ret = 0; int optSz; int rc; @@ -1675,7 +1679,7 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, if (ret == 0) { switch (version) { case WOLFSSL_EXPORT_VERSION: - if (!isTLS) { + if (type == WOLFSSL_EXPORT_DTLS) { optSz = DTLS_EXPORT_OPT_SZ; } else { @@ -1708,7 +1712,7 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, } if (ret == 0) { - rc = ImportOptions(ssl, buf + idx, length, version, isTLS); + rc = ImportOptions(ssl, buf + idx, length, version, type); if (rc < 0) { WOLFSSL_MSG("Import Options struct error"); ret = rc; @@ -1733,7 +1737,7 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, } if (ret == 0) { - rc = ImportKeyState(ssl, buf + idx, length, version, isTLS); + rc = ImportKeyState(ssl, buf + idx, length, version, type); if (rc < 0) { WOLFSSL_MSG("Import Key struct error"); ret = rc; @@ -1758,7 +1762,7 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, } if (ret == 0) { - rc = ImportCipherSpecState(ssl, buf + idx, length, version, isTLS); + rc = ImportCipherSpecState(ssl, buf + idx, length, version, type); if (rc < 0) { WOLFSSL_MSG("Import CipherSpecs struct error"); ret = rc; @@ -1828,13 +1832,13 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, * @param ssl WOLFSSL structure to serialize session from * @param buf output buffer to hold serialized session * @param sz the size of buffer 'buf', if too small then gets updated - * @param isTLS if the input WOLFSSL structure is expected to be TLS or DTLS + * @param type if the input WOLFSSL structure is expected to be TLS or DTLS * 1 for yes is TLS and 0 for no is DTLS * * @return the size of serialized buffer on success and negative values on fail */ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, - int isTLS) + int type) { int ret = 0; word32 idx = 0; @@ -1854,7 +1858,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, totalLen += WOLFSSL_EXPORT_LEN + DTLS_EXPORT_KEY_SZ; totalLen += WOLFSSL_EXPORT_LEN + WOLFSSL_EXPORT_SPC_SZ; #ifdef WOLFSSL_DTLS - if (!isTLS) { + if (type == WOLFSSL_EXPORT_DTLS) { totalLen += WOLFSSL_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz; } #endif @@ -1866,22 +1870,24 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, *sz = totalLen; /* possible AES state needed */ - if (isTLS) { + if (type == WOLFSSL_EXPORT_TLS) { *sz += AES_BLOCK_SIZE*2; } ret = LENGTH_ONLY_E; } if (ret == 0) { - buf[idx++] = (byte)(isTLS)? TLS_EXPORT_PRO : DTLS_EXPORT_PRO; - buf[idx++] = ((byte)((isTLS)? TLS_EXPORT_PRO : DTLS_EXPORT_PRO) & 0xF0) - | ((byte)WOLFSSL_EXPORT_VERSION & 0X0F); + buf[idx++] = (byte)(type == WOLFSSL_EXPORT_TLS)? TLS_EXPORT_PRO : + DTLS_EXPORT_PRO; + buf[idx++] = ((byte)((type == WOLFSSL_EXPORT_TLS)? TLS_EXPORT_PRO : + DTLS_EXPORT_PRO) & 0xF0) + | ((byte)WOLFSSL_EXPORT_VERSION & 0X0F); idx += WOLFSSL_EXPORT_LEN; /* leave spot for length of total buffer */ idx += WOLFSSL_EXPORT_LEN; ret = ExportOptions(ssl, buf + idx, *sz - idx, WOLFSSL_EXPORT_VERSION, - isTLS); + type); if (ret >= 0) { c16toa((word16)ret, buf + idx - WOLFSSL_EXPORT_LEN); idx += ret; @@ -1893,7 +1899,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, if (ret == 0) { idx += WOLFSSL_EXPORT_LEN; /* leave room for length */ ret = ExportKeyState(ssl, buf + idx, *sz - idx, WOLFSSL_EXPORT_VERSION, - 0, isTLS); + 0, type); if (ret >= 0) { c16toa((word16)ret, buf + idx - WOLFSSL_EXPORT_LEN); idx += ret; ret = 0; @@ -1905,7 +1911,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, c16toa((word16)WOLFSSL_EXPORT_SPC_SZ, buf + idx); idx += WOLFSSL_EXPORT_LEN; ret = ExportCipherSpecState(ssl, buf + idx, *sz - idx, - WOLFSSL_EXPORT_VERSION, isTLS); + WOLFSSL_EXPORT_VERSION, type); if (ret >= 0) { idx += ret; ret = 0; diff --git a/tests/api.c b/tests/api.c index 238f5cd74..210532acd 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5650,8 +5650,9 @@ static void test_wolfSSL_dtls_export(void) } -#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) -static byte canned_client_session[] = { +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) &&\ + !defined(WOLFSSL_NO_TLS12) +static const byte canned_client_session[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, @@ -5696,7 +5697,7 @@ static byte canned_client_session[] = { }; -static byte canned_server_session[] = { +static const byte canned_server_session[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, @@ -5868,7 +5869,8 @@ done: static void test_wolfSSL_tls_export(void) { -#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) &&\ + !defined(WOLFSSL_NO_TLS12) SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 55cb14556..9bac559d8 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1333,7 +1333,9 @@ enum Misc { /* min amount of bytes used from Keys */ WOLFSSL_EXPORT_TLS = 1, WOLFSSL_EXPORT_DTLS = 0, +#ifndef WOLFSSL_EXPORT_SPC_SZ WOLFSSL_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */ +#endif WOLFSSL_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ WOLFSSL_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ From dd7b62d0672a169d2fa8970e991250c9dd4d5c12 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 29 Sep 2021 11:15:51 -0600 Subject: [PATCH 11/13] fix for use with idea enabled --- tests/api.c | 6 ++---- wolfssl/ssl.h | 31 ++++++++++++++++--------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/tests/api.c b/tests/api.c index 210532acd..2bc9a5d16 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5650,8 +5650,7 @@ static void test_wolfSSL_dtls_export(void) } -#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) &&\ - !defined(WOLFSSL_NO_TLS12) +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) static const byte canned_client_session[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, @@ -5869,8 +5868,7 @@ done: static void test_wolfSSL_tls_export(void) { -#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IDEA) &&\ - !defined(WOLFSSL_NO_TLS12) +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 7b3f0b7d5..5b22cc632 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2927,24 +2927,25 @@ enum { WOLFSSL_TLS_HMAC_INNER_SZ = 13 /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */ }; -/* for GetBulkCipher and internal use */ +/* for GetBulkCipher and internal use + * using explicit values to assist with serialization of a TLS session */ enum BulkCipherAlgorithm { - wolfssl_cipher_null, - wolfssl_rc4, - wolfssl_rc2, - wolfssl_des, - wolfssl_triple_des, /* leading 3 (3des) not valid identifier */ - wolfssl_des40, + wolfssl_cipher_null = 0, + wolfssl_rc4 = 1, + wolfssl_rc2 = 2, + wolfssl_des = 3, + wolfssl_triple_des = 4, + wolfssl_des40 = 5, + wolfssl_aes = 6, + wolfssl_aes_gcm = 7, + wolfssl_aes_ccm = 8, + wolfssl_chacha = 9, + wolfssl_camellia = 10, + wolfssl_hc128 = 11, + wolfssl_rabbit = 12, #ifdef HAVE_IDEA - wolfssl_idea, + wolfssl_idea = 13 #endif - wolfssl_aes, - wolfssl_aes_gcm, - wolfssl_aes_ccm, - wolfssl_chacha, - wolfssl_camellia, - wolfssl_hc128, /* wolfSSL extensions */ - wolfssl_rabbit }; From cb4b57c5c714ede45b1c4a008c9aa26d2dd9eab0 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 30 Sep 2021 10:08:47 -0600 Subject: [PATCH 12/13] add tls 1.3 test case --- doc/dox_comments/header_files/ssl.h | 9 +- src/internal.c | 24 +++-- src/ssl.c | 12 +-- tests/api.c | 158 +++++++++++++++++++++++++--- wolfssl/internal.h | 4 +- 5 files changed, 171 insertions(+), 36 deletions(-) diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index f5b8a8512..4fceb5033 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -702,11 +702,14 @@ WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz); /*! - \brief Used to export a serialized TLS session. In most cases - wolfSSL_set_session should be used instead, this function is for importing a - serialized state of the connection. + \brief Used to export a serialized TLS session. This function is for + importing a serialized state of the connection. + In most cases wolfSSL_get_session should be used instead of + wolfSSL_tls_export. Additional debug info can be displayed with the macro WOLFSSL_SESSION_EXPORT_DEBUG defined. + WARNING: buf contains sensitive information about the state and is best to + be encrypted before storing if stored. \return the number of bytes written into buffer 'buf' diff --git a/src/internal.c b/src/internal.c index 7447d904a..9b5e2def2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -601,7 +601,7 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, return BAD_FUNC_ARG; } - specs= &ssl->specs; + specs = &ssl->specs; if (WOLFSSL_EXPORT_SPC_SZ > len) { return BUFFER_E; } @@ -1186,10 +1186,10 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, exp[idx++] = options->asyncState; if (type == WOLFSSL_EXPORT_TLS) { - exp[idx++] = ssl->options.disallowEncThenMac; - exp[idx++] = ssl->options.encThenMac; - exp[idx++] = ssl->options.startedETMRead; - exp[idx++] = ssl->options.startedETMWrite; + exp[idx++] = options->disallowEncThenMac; + exp[idx++] = options->encThenMac; + exp[idx++] = options->startedETMRead; + exp[idx++] = options->startedETMWrite; } /* version of connection */ @@ -1362,10 +1362,10 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, options->asyncState = exp[idx++]; if (type == WOLFSSL_EXPORT_TLS) { - ssl->options.disallowEncThenMac = exp[idx++]; - ssl->options.encThenMac = exp[idx++]; - ssl->options.startedETMRead = exp[idx++]; - ssl->options.startedETMWrite = exp[idx++]; + options->disallowEncThenMac = exp[idx++]; + options->encThenMac = exp[idx++]; + options->startedETMRead = exp[idx++]; + options->startedETMWrite = exp[idx++]; } /* version of connection */ @@ -1374,6 +1374,12 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, return VERSION_ERROR; } + /* set TLS 1.3 flag in options if this was a TLS 1.3 connection */ + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor == TLSv1_3_MINOR) { + options->tls1_3 = 1; + } + return idx; } diff --git a/src/ssl.c b/src/ssl.c index 9391974f8..1f3d292e2 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -239,10 +239,7 @@ byte tsip_rootCAverified( ); #endif #ifdef WOLFSSL_SESSION_EXPORT -/** - * Used to import a serialized TLS session. In most cases wolfSSL_get_session - * should be used instead, this function is for exporting the state of the - * connection and when imported a resumption is not needed. +/* Used to import a serialized TLS session. * WARNING: buf contains sensitive information about the state and is best to be * encrypted before storing if stored. * @@ -260,10 +257,9 @@ int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) } -/** - * Used to export a serialized TLS session. In most cases wolfSSL_set_session - * should be used instead, this function is for importing a serialized state of - * the connection. +/* Used to export a serialized TLS session. + * WARNING: buf contains sensitive information about the state and is best to be + * encrypted before storing if stored. * * @param ssl WOLFSSL structure to export the session from * @param buf output of serialized session diff --git a/tests/api.c b/tests/api.c index 2bc9a5d16..4fd1d9c56 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5651,6 +5651,86 @@ static void test_wolfSSL_dtls_export(void) #if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) +#ifdef WOLFSSL_TLS13 +static const byte canned_client_tls13_session[] = { + 0xA7, 0xA4, 0x01, 0x18, 0x00, 0x41, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, + 0x01, 0x0A, 0x0F, 0x10, 0x01, 0x02, 0x09, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, + 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x11, 0x01, 0x01, 0x00, 0x20, 0x84, 0x4F, 0x18, + 0xD8, 0xC1, 0x24, 0xD8, 0xBB, 0x17, 0x9E, 0x31, + 0xA3, 0xF8, 0xA7, 0x3C, 0xBA, 0xEC, 0xFA, 0xB4, + 0x7F, 0xC5, 0x78, 0xEB, 0x6D, 0xE3, 0x2B, 0x7B, + 0x94, 0xBE, 0x20, 0x11, 0x7E, 0x17, 0x10, 0xA7, + 0x10, 0x19, 0xEC, 0x62, 0xCC, 0xBE, 0xF5, 0x01, + 0x35, 0x3C, 0xEA, 0xEF, 0x44, 0x3C, 0x40, 0xA2, + 0xBC, 0x18, 0x43, 0xA1, 0xA1, 0x65, 0x5C, 0x48, + 0xE2, 0xF9, 0x38, 0xEB, 0x11, 0x10, 0x72, 0x7C, + 0x78, 0x22, 0x13, 0x3B, 0x19, 0x40, 0xF0, 0x73, + 0xBE, 0x96, 0x14, 0x78, 0x26, 0xB9, 0x6B, 0x2E, + 0x72, 0x22, 0x0D, 0x90, 0x94, 0xDD, 0x78, 0x77, + 0xFC, 0x0C, 0x2E, 0x63, 0x6E, 0xF0, 0x0C, 0x35, + 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, 0x6F, + 0x02, 0x3D, 0xC1, 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, + 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0x35, 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, + 0x6F, 0x02, 0x3D, 0xC1, 0xD3, 0xB7, 0xEE, 0x3A, + 0xA0, 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x10, + 0x00, 0x10, 0x07, 0x02, 0x04, 0x00, 0x00, 0x20, + 0x28, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03 +}; + +static const byte canned_server_tls13_session[] = { + 0xA7, 0xA4, 0x01, 0x18, 0x00, 0x41, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, + 0x01, 0x0A, 0x0F, 0x10, 0x01, 0x02, 0x00, 0x0F, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, + 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x11, 0x01, 0x01, 0x00, 0x20, 0x84, 0x4F, 0x18, + 0xD8, 0xC1, 0x24, 0xD8, 0xBB, 0x17, 0x9E, 0x31, + 0xA3, 0xF8, 0xA7, 0x3C, 0xBA, 0xEC, 0xFA, 0xB4, + 0x7F, 0xC5, 0x78, 0xEB, 0x6D, 0xE3, 0x2B, 0x7B, + 0x94, 0xBE, 0x20, 0x11, 0x7E, 0x17, 0x10, 0xA7, + 0x10, 0x19, 0xEC, 0x62, 0xCC, 0xBE, 0xF5, 0x01, + 0x35, 0x3C, 0xEA, 0xEF, 0x44, 0x3C, 0x40, 0xA2, + 0xBC, 0x18, 0x43, 0xA1, 0xA1, 0x65, 0x5C, 0x48, + 0xE2, 0xF9, 0x38, 0xEB, 0x11, 0x10, 0x72, 0x7C, + 0x78, 0x22, 0x13, 0x3B, 0x19, 0x40, 0xF0, 0x73, + 0xBE, 0x96, 0x14, 0x78, 0x26, 0xB9, 0x6B, 0x2E, + 0x72, 0x22, 0x0D, 0x90, 0x94, 0xDD, 0x78, 0x77, + 0xFC, 0x0C, 0x2E, 0x63, 0x6E, 0xF0, 0x0C, 0x35, + 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, 0x6F, + 0x02, 0x3D, 0xC1, 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, + 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, 0x8E, 0xA1, 0x4D, + 0xC3, 0x2E, 0x5E, 0x06, 0x35, 0x41, 0xCD, 0xF3, + 0x49, 0x31, 0x08, 0xD0, 0x6F, 0x02, 0x3D, 0xC1, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x10, + 0x00, 0x10, 0x07, 0x02, 0x04, 0x00, 0x00, 0x20, + 0x28, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04 +}; +#endif /* WOLFSSL_TLS13 */ + static const byte canned_client_session[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, @@ -5801,15 +5881,12 @@ static THREAD_RETURN WOLFSSL_THREAD tls_export_server(void* args) if (ssl == NULL) { goto done; } + wolfSSL_set_fd(ssl, clientfd); /* call ssl setup callback */ if (cbf != NULL && cbf->ssl_ready != NULL) { cbf->ssl_ready(ssl); } - AssertIntEQ(wolfSSL_tls_import(ssl, canned_server_session, - sizeof(canned_server_session)), sizeof(canned_server_session)); - wolfSSL_set_fd(ssl, clientfd); - idx = wolfSSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { input[idx] = '\0'; @@ -5864,11 +5941,32 @@ done: return 0; #endif } + + +static void load_tls12_canned_server(WOLFSSL* ssl) +{ + int clientfd = wolfSSL_get_fd(ssl); + AssertIntEQ(wolfSSL_tls_import(ssl, canned_server_session, + sizeof(canned_server_session)), sizeof(canned_server_session)); + wolfSSL_set_fd(ssl, clientfd); +} + + +#ifdef WOLFSSL_TLS13 +static void load_tls13_canned_server(WOLFSSL* ssl) +{ + int clientfd = wolfSSL_get_fd(ssl); + AssertIntEQ(wolfSSL_tls_import(ssl, canned_server_tls13_session, + sizeof(canned_server_tls13_session)), + sizeof(canned_server_tls13_session)); + wolfSSL_set_fd(ssl, clientfd); +} #endif -static void test_wolfSSL_tls_export(void) + +/* v is for version WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */ +static void test_wolfSSL_tls_export_run(int v) { -#if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; @@ -5876,13 +5974,14 @@ static void test_wolfSSL_tls_export(void) char reply[1024]; word32 replySz; int msgSz = (int)XSTRLEN(msg); + const byte* clientSession = NULL; + int clientSessionSz = 0; tcp_ready ready; func_args server_args; THREAD_TYPE serverThread; callback_functions server_cbf; - printf(testingFmt, "wolfSSL_tls_export()"); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif @@ -5896,9 +5995,31 @@ static void test_wolfSSL_tls_export(void) XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); - server_cbf.method = wolfTLSv1_2_server_method; + switch (v) { + case WOLFSSL_TLSV1_2: + server_cbf.method = wolfTLSv1_2_server_method; + server_cbf.ssl_ready = load_tls12_canned_server; + + /* setup the client side */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); + wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256"); + clientSession = canned_client_session; + clientSessionSz = sizeof(canned_client_session); + break; + #ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + server_cbf.method = wolfTLSv1_3_server_method; + server_cbf.ssl_ready = load_tls13_canned_server; + + /* setup the client side */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); + clientSession = canned_client_tls13_session; + clientSessionSz = sizeof(canned_client_tls13_session); + break; + #endif + } server_args.callbacks = &server_cbf; - server_args.signal = &ready; + server_args.signal = &ready; start_thread(tls_export_server, &server_args, &serverThread); wait_tcp_ready(&server_args); @@ -5908,15 +6029,13 @@ static void test_wolfSSL_tls_export(void) fdOpenSession(Task_self()); #endif - AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); - wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256"); AssertNotNull(ssl = wolfSSL_new(ctx)); tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl); - AssertIntEQ(wolfSSL_tls_import(ssl, canned_client_session, - sizeof(canned_client_session)), sizeof(canned_client_session)); + AssertIntEQ(wolfSSL_tls_import(ssl, clientSession, clientSessionSz), + clientSessionSz); replySz = sizeof(reply); AssertIntGT(wolfSSL_tls_export(ssl, (byte*)reply, &replySz), 0); - AssertIntEQ(XMEMCMP(reply, canned_client_session, replySz), 0); + AssertIntEQ(XMEMCMP(reply, clientSession, replySz), 0); wolfSSL_set_fd(ssl, sockfd); AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); @@ -5945,6 +6064,17 @@ static void test_wolfSSL_tls_export(void) fdOpenSession(Task_self()); #endif +} +#endif + +static void test_wolfSSL_tls_export(void) +{ +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) + printf(testingFmt, "wolfSSL_tls_export()"); + test_wolfSSL_tls_export_run(WOLFSSL_TLSV1_2); + #ifdef WOLFSSL_TLS13 + test_wolfSSL_tls_export_run(WOLFSSL_TLSV1_3); + #endif printf(resultFmt, passed); #endif } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9bac559d8..d9ee87778 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1666,9 +1666,9 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); #endif #ifdef WOLFSSL_SESSION_EXPORT WOLFSSL_LOCAL int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, - word32* sz, int isTLS); + word32* sz, int type); WOLFSSL_LOCAL int wolfSSL_session_import_internal(WOLFSSL* ssl, const byte* buf, - word32 sz, int isTLS); + word32 sz, int type); #ifdef WOLFSSL_DTLS WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz); From ed8b87306d71b252b405ba60013e246f5936fdd2 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 30 Sep 2021 15:48:55 -0600 Subject: [PATCH 13/13] account for test case where psk and anon is off --- tests/api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/api.c b/tests/api.c index 4fd1d9c56..c61adce10 100644 --- a/tests/api.c +++ b/tests/api.c @@ -6035,7 +6035,10 @@ static void test_wolfSSL_tls_export_run(int v) clientSessionSz); replySz = sizeof(reply); AssertIntGT(wolfSSL_tls_export(ssl, (byte*)reply, &replySz), 0); +#if !defined(NO_PSK) && defined(HAVE_ANON) + /* index 20 has is setting if PSK was on and 49 is if anon is allowed */ AssertIntEQ(XMEMCMP(reply, clientSession, replySz), 0); +#endif wolfSSL_set_fd(ssl, sockfd); AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz);