Convert the TLSv1.3 crypto code to the new write record layer

We also clean up some of the KTLS code while we are doing it now that all
users of KTLS have been moved to the new write record layer.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19343)
This commit is contained in:
Matt Caswell 2022-09-16 17:34:40 +01:00
parent ef917549f5
commit 2c50d7fb06
9 changed files with 52 additions and 274 deletions

View File

@ -18,49 +18,6 @@
#if defined(__FreeBSD__)
# include "crypto/cryptodev.h"
/*
* TODO(RECLAYER): This is essentially a copy of ktls_int_check_supported_cipher
* but using an SSL object instead of an OSSL_RECORD_LAYER object. Once
* the write side has been moved to the record layer this can be deleted
*/
int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
const EVP_MD *md, size_t taglen)
{
switch (s->version) {
case TLS1_VERSION:
case TLS1_1_VERSION:
case TLS1_2_VERSION:
case TLS1_3_VERSION:
break;
default:
return 0;
}
if (EVP_CIPHER_is_a(c, "AES-128-GCM")
|| EVP_CIPHER_is_a(c, "AES-256-GCM")
# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
|| EVP_CIPHER_is_a(c, "CHACHA20-POLY1305")
# endif
)
return 1;
if (!EVP_CIPHER_is_a(c, "AES-128-CBC")
&& !EVP_CIPHER_is_a(c, "AES-256-CBC"))
return 0;
if (s->ext.use_etm)
return 0;
if (md == NULL
|| EVP_MD_is_a(md, "SHA1")
|| EVP_MD_is_a(md, "SHA2-256")
|| EVP_MD_is_a(md, "SHA2-384"))
return 1;
return 0;
}
/*-
* Check if a given cipher is supported by the KTLS interface.
* The kernel might still fail the setsockopt() if no suitable
@ -76,7 +33,9 @@ static int ktls_int_check_supported_cipher(OSSL_RECORD_LAYER *rl,
case TLS1_VERSION:
case TLS1_1_VERSION:
case TLS1_2_VERSION:
#ifdef OPENSSL_KTLS_TLS13
case TLS1_3_VERSION:
#endif
break;
default:
return 0;
@ -109,6 +68,7 @@ static int ktls_int_check_supported_cipher(OSSL_RECORD_LAYER *rl,
}
/* Function to configure kernel TLS structure */
static
int ktls_configure_crypto(OSSL_LIB_CTX *libctx, int version, const EVP_CIPHER *c,
EVP_MD *md, void *rl_sequence,
ktls_crypto_info_t *crypto_info, int is_tx,
@ -163,51 +123,6 @@ int ktls_configure_crypto(OSSL_LIB_CTX *libctx, int version, const EVP_CIPHER *c
#endif /* __FreeBSD__ */
#if defined(OPENSSL_SYS_LINUX)
/*
* TODO(RECLAYER): This is essentially a copy of ktls_int_check_supported_cipher
* but using an SSL object instead of an OSSL_RECORD_LAYER object. Once
* the write side has been moved to the record layer this can be deleted
*/
int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
const EVP_MD *md, size_t taglen)
{
switch (s->version) {
case TLS1_2_VERSION:
case TLS1_3_VERSION:
break;
default:
return 0;
}
/*
* Check that cipher is AES_GCM_128, AES_GCM_256, AES_CCM_128
* or Chacha20-Poly1305
*/
# ifdef OPENSSL_KTLS_AES_CCM_128
if (EVP_CIPHER_is_a(c, "AES-128-CCM")) {
if (s->version == TLS_1_3_VERSION /* broken on 5.x kernels */
|| taglen != EVP_CCM_TLS_TAG_LEN)
return 0;
return 1;
} else
# endif
if (0
# ifdef OPENSSL_KTLS_AES_GCM_128
|| EVP_CIPHER_is_a(c, "AES-128-GCM")
# endif
# ifdef OPENSSL_KTLS_AES_GCM_256
|| EVP_CIPHER_is_a(c, "AES-256-GCM")
# endif
# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
|| EVP_CIPHER_is_a(c, "ChaCha20-Poly1305")
# endif
) {
return 1;
}
return 0;
}
/* Function to check supported ciphers in Linux */
static int ktls_int_check_supported_cipher(OSSL_RECORD_LAYER *rl,
const EVP_CIPHER *c,
@ -216,7 +131,9 @@ static int ktls_int_check_supported_cipher(OSSL_RECORD_LAYER *rl,
{
switch (rl->version) {
case TLS1_2_VERSION:
#ifdef OPENSSL_KTLS_TLS13
case TLS1_3_VERSION:
#endif
break;
default:
return 0;
@ -251,6 +168,7 @@ static int ktls_int_check_supported_cipher(OSSL_RECORD_LAYER *rl,
}
/* Function to configure kernel TLS structure */
static
int ktls_configure_crypto(OSSL_LIB_CTX *libctx, int version, const EVP_CIPHER *c,
const EVP_MD *md, void *rl_sequence,
ktls_crypto_info_t *crypto_info, int is_tx,
@ -518,13 +436,6 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
(*retrl)->funcs = &ossl_ktls_funcs;
/*
* TODO(RECLAYER): We're not ready to set the crypto state for the write
* record layer in TLSv1.3. Fix this once we are
*/
if (direction == OSSL_RECORD_DIRECTION_WRITE && vers == TLS1_3_VERSION)
return 1;
ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
ivlen, mackey, mackeylen, ciph,
taglen, mactype, md, comp);

View File

@ -25,6 +25,7 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
{
EVP_CIPHER_CTX *ciph_ctx;
int mode;
int enc = (rl->direction == OSSL_RECORD_DIRECTION_WRITE) ? 1 : 0;
if (ivlen > sizeof(rl->iv)) {
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
@ -42,13 +43,13 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
mode = EVP_CIPHER_get_mode(ciph);
if (EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, NULL, NULL) <= 0
if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, enc) <= 0
|| EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen,
NULL) <= 0
|| (mode == EVP_CIPH_CCM_MODE
&& EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen,
NULL) <= 0)
|| EVP_DecryptInit_ex(ciph_ctx, NULL, NULL, key, NULL) <= 0) {
|| EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, enc) <= 0) {
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}

View File

@ -1465,11 +1465,8 @@ size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl)
size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag)
{
/* TODO(RECLAYER): Remove me */
SSL_CONNECTION *s = rl->cbarg;
/*
* TODO(RECLYAER): There is no test for the pipelining code. We should add
* TODO(RECLAYER): There is no test for the pipelining code. We should add
* one.
*/
/*
@ -1477,8 +1474,8 @@ size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len,
* it, then return the preferred number of pipelines.
*/
if (rl->max_pipelines > 0
&& s->enc_write_ctx != NULL
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
&& rl->enc_ctx!= NULL
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(rl->enc_ctx))
& EVP_CIPH_FLAG_PIPELINE) != 0
&& RLAYER_USE_EXPLICIT_IV(rl)) {
size_t pipes;
@ -1521,11 +1518,10 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *thistempl;
/*
* TODO(RECLAYER): Remove this once TLSv1.3/DTLS crypto has
* TODO(RECLAYER): Remove this once DTLS crypto has
* been moved to the new write record layer.
*/
if (rl->version == TLS1_3_VERSION
|| rl->isdtls) {
if (rl->isdtls) {
SSL_SESSION *sess = s->session;
if ((sess == NULL)
@ -1644,7 +1640,7 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
* record type
*/
if (rl->version == TLS1_3_VERSION
&& s->enc_write_ctx != NULL
&& rl->enc_ctx != NULL
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|| thistempl->type != SSL3_RT_ALERT))
rectype = SSL3_RT_APPLICATION_DATA;
@ -1707,7 +1703,7 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
if (rl->version == TLS1_3_VERSION
&& !using_ktls
&& s->enc_write_ctx != NULL
&& rl->enc_ctx != NULL
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|| thistempl->type != SSL3_RT_ALERT)) {
size_t rlen, max_send_fragment;
@ -1766,11 +1762,10 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
unsigned char *mac;
/*
* TODO(RECLAYER): Remove this once TLSv1.3/DTLS crypto has
* TODO(RECLAYER): Remove this once DTLS crypto has
* been moved to the new write record layer.
*/
if (rl->version == TLS1_3_VERSION
|| rl->isdtls) {
if (rl->isdtls) {
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
|| !ssl->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
@ -1816,8 +1811,9 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
* We haven't actually negotiated the version yet, but we're trying to
* send early data - so we need to use the tls13enc function.
*/
if (tls13_enc(s, wr, numtempl, 1, NULL, mac_size) < 1) {
if (!ossl_statem_in_error(s))
/* TODO(RECLAYER): Is this branch necessary now? */
if (rl->funcs->cipher(rl, wr, numtempl, 1, NULL, mac_size) < 1) {
if (!ossl_statem_in_error(s)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
@ -1831,11 +1827,10 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
}
}
/*
* TODO(RECLAYER): Remove this once TLSv1.3/DTLS crypto has
* TODO(RECLAYER): Remove this once DTLS crypto has
* been moved to the new write record layer.
*/
if (rl->version == TLS1_3_VERSION
|| rl->isdtls) {
if (rl->isdtls) {
if (ssl->method->ssl3_enc->enc(s, wr + prefix, numtempl, 1, NULL,
mac_size) < 1) {
if (!ossl_statem_in_error(s))
@ -1879,11 +1874,10 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
unsigned char *mac;
/*
* TODO(RECLAYER): Remove this once TLSv1.3/DTLS crypto has
* TODO(RECLAYER): Remove this once DTLS crypto has
* been moved to the new write record layer.
*/
if (rl->version == TLS1_3_VERSION
|| rl->isdtls) {
if (rl->isdtls) {
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
|| !ssl->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);

View File

@ -1062,6 +1062,7 @@ static const OSSL_DISPATCH rlayer_dispatch[] = {
};
static const OSSL_RECORD_METHOD *ssl_select_next_record_layer(SSL_CONNECTION *s,
int direction,
int level)
{
@ -1081,7 +1082,8 @@ static const OSSL_RECORD_METHOD *ssl_select_next_record_layer(SSL_CONNECTION *s,
#endif
/* Default to the current OSSL_RECORD_METHOD */
return s->rlayer.rrlmethod;
return direction == OSSL_RECORD_DIRECTION_READ ? s->rlayer.rrlmethod
: s->rlayer.wrlmethod;
}
static int ssl_post_record_layer_select(SSL_CONNECTION *s, int direction)
@ -1138,7 +1140,7 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
uint32_t max_early_data;
COMP_METHOD *compm = (comp == NULL) ? NULL : comp->method;
meth = ssl_select_next_record_layer(s, level);
meth = ssl_select_next_record_layer(s, direction, level);
if (direction == OSSL_RECORD_DIRECTION_READ) {
thismethod = &s->rlayer.rrlmethod;

View File

@ -2852,18 +2852,6 @@ __owur int ssl_log_secret(SSL_CONNECTION *s, const char *label,
#define EARLY_EXPORTER_SECRET_LABEL "EARLY_EXPORTER_SECRET"
#define EXPORTER_SECRET_LABEL "EXPORTER_SECRET"
# ifndef OPENSSL_NO_KTLS
/* ktls.c */
int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
const EVP_MD *md, size_t taglen);
int ktls_configure_crypto(OSSL_LIB_CTX *libctx, int version,
const EVP_CIPHER *c, const EVP_MD *md,
void *rl_sequence, ktls_crypto_info_t *crypto_info,
int is_tx, unsigned char *iv, size_t ivlen,
unsigned char *key, size_t keylen,
unsigned char *mac_key, size_t mac_secret_size);
# endif
__owur int srp_generate_server_master_secret(SSL_CONNECTION *s);
__owur int srp_generate_client_master_secret(SSL_CONNECTION *s);
__owur int srp_verify_server_param(SSL_CONNECTION *s);

View File

@ -682,6 +682,22 @@ WORK_STATE ossl_statem_client_pre_work(SSL_CONNECTION *s, WORK_STATE wst)
/* SSLfatal() already called */
return WORK_ERROR;
}
} else if (s->ext.early_data == SSL_EARLY_DATA_REJECTED) {
/*
* This must be a second ClientHello after an HRR following an
* earlier rejected attempt to send early data. Since we were
* previously encrypting the early data we now need to reset the
* write record layer in order to write in plaintext again.
*/
if (!ssl_set_new_record_layer(s,
TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_WRITE,
OSSL_RECORD_PROTECTION_LEVEL_NONE,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
NID_undef, NULL, NULL)) {
/* SSLfatal already called */
return WORK_ERROR;
}
}
break;
@ -767,15 +783,6 @@ WORK_STATE ossl_statem_client_post_work(SSL_CONNECTION *s, WORK_STATE wst)
}
break;
case TLS_ST_CW_END_OF_EARLY_DATA:
/*
* We set the enc_write_ctx back to NULL because we may end up writing
* in cleartext again if we get a HelloRetryRequest from the server.
*/
EVP_CIPHER_CTX_free(s->enc_write_ctx);
s->enc_write_ctx = NULL;
break;
case TLS_ST_CW_KEY_EXCH:
if (tls_client_key_exchange_post_work(s) == 0) {
/* SSLfatal() already called */

View File

@ -165,11 +165,6 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
size_t n, i, j, k, cl;
int iivlen;
int reuse_dd = 0;
#ifndef OPENSSL_NO_KTLS
ktls_crypto_info_t crypto_info;
void *rl_sequence;
BIO *bio;
#endif
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
/*
* Taglen is only relevant for CCM ciphersuites. Other ciphersuites
@ -253,7 +248,7 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
}
/* TODO(RECLAYER): Temporary - remove me when DTLS write rlayer done*/
goto skip_ktls;
goto done;
} else {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->ext.use_etm)
@ -283,7 +278,7 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
/* TODO(RECLAYER): Temporary - remove me when DTLS write rlayer done*/
if (!SSL_CONNECTION_IS_DTLS(s))
goto skip_ktls;
goto done;
if (s->enc_write_ctx != NULL && !SSL_CONNECTION_IS_DTLS(s)) {
reuse_dd = 1;
@ -394,57 +389,7 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
goto err;
}
#ifndef OPENSSL_NO_KTLS
if (s->compress || (s->options & SSL_OP_ENABLE_KTLS) == 0)
goto skip_ktls;
/* ktls supports only the maximum fragment size */
if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
goto skip_ktls;
/* check that cipher is supported */
if (!ktls_check_supported_cipher(s, c, m, taglen))
goto skip_ktls;
if (which & SSL3_CC_WRITE)
bio = s->wbio;
else
bio = s->rbio;
if (!ossl_assert(bio != NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
if (which & SSL3_CC_WRITE) {
if (BIO_flush(bio) <= 0)
goto skip_ktls;
}
/* ktls doesn't support renegotiation */
if ((BIO_get_ktls_send(s->wbio) && (which & SSL3_CC_WRITE)) ||
(BIO_get_ktls_recv(s->rbio) && (which & SSL3_CC_READ))) {
SSLfatal(s, SSL_AD_NO_RENEGOTIATION, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* If we get here we are only doing the write side. The read side goes
* through the new record layer code.
*/
rl_sequence = RECORD_LAYER_get_write_sequence(&s->rlayer);
if (!ktls_configure_crypto(sctx->libctx, s->version, c, m, rl_sequence,
&crypto_info, which & SSL3_CC_WRITE, iv,
(size_t)k, key, cl, mac_secret, mac_secret_size))
goto skip_ktls;
/* ktls works with user provided buffers directly */
if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE))
SSL_set_options(SSL_CONNECTION_GET_SSL(s), SSL_OP_NO_RENEGOTIATION);
#endif /* OPENSSL_NO_KTLS */
skip_ktls:
done:
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
OSSL_TRACE_BEGIN(TLS) {

View File

@ -461,11 +461,6 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
int level;
int direction = (which & SSL3_CC_READ) != 0 ? OSSL_RECORD_DIRECTION_READ
: OSSL_RECORD_DIRECTION_WRITE;
#if !defined(OPENSSL_NO_KTLS) && defined(OPENSSL_KTLS_TLS13)
ktls_crypto_info_t crypto_info;
void *rl_sequence;
BIO *bio;
#endif
if (which & SSL3_CC_READ) {
iv = s->read_iv;
@ -719,59 +714,6 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
goto err;
}
if ((which & SSL3_CC_READ) != 0) {
/* TODO(RECLAYER): Remove me when write rlayer done */
goto skip_ktls;
}
#ifndef OPENSSL_NO_KTLS
# if defined(OPENSSL_KTLS_TLS13)
if (!(which & SSL3_CC_APPLICATION)
|| (s->options & SSL_OP_ENABLE_KTLS) == 0)
goto skip_ktls;
/* ktls supports only the maximum fragment size */
if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
goto skip_ktls;
/* ktls does not support record padding */
if (s->rlayer.record_padding_cb != NULL || s->rlayer.block_padding > 0)
goto skip_ktls;
/* check that cipher is supported */
if (!ktls_check_supported_cipher(s, cipher, NULL, taglen))
goto skip_ktls;
if (which & SSL3_CC_WRITE)
bio = s->wbio;
else
bio = s->rbio;
if (!ossl_assert(bio != NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
if (which & SSL3_CC_WRITE) {
if (BIO_flush(bio) <= 0)
goto skip_ktls;
}
/* configure kernel crypto structure */
/*
* If we get here we are only doing the write side. The read side goes
* through the new record layer code.
*/
rl_sequence = RECORD_LAYER_get_write_sequence(&s->rlayer);
if (!ktls_configure_crypto(sctx->libctx, s->version, cipher, NULL,
rl_sequence, &crypto_info, which & SSL3_CC_WRITE,
iv, ivlen, key, keylen, NULL, 0))
goto skip_ktls;
# endif
#endif
skip_ktls:
ret = 1;
err:
if ((which & SSL3_CC_EARLY) != 0) {

View File

@ -1073,14 +1073,8 @@ static int ping_pong_query(SSL *clientssl, SSL *serverssl)
goto end;
cbuf[0] = count++;
/* TODO(RECLAYER): Remove me once TLSv1.3 write side converted */
if (SSL_CONNECTION_IS_TLS13(serversc)) {
memcpy(crec_wseq_before, &clientsc->rlayer.write_sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_before, &serversc->rlayer.write_sequence, SEQ_NUM_SIZE);
} else {
memcpy(crec_wseq_before, &clientsc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_before, &serversc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
}
memcpy(crec_wseq_before, &clientsc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_before, &serversc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
memcpy(crec_rseq_before, &clientsc->rlayer.rrl->sequence, SEQ_NUM_SIZE);
memcpy(srec_rseq_before, &serversc->rlayer.rrl->sequence, SEQ_NUM_SIZE);
@ -1102,14 +1096,8 @@ static int ping_pong_query(SSL *clientssl, SSL *serverssl)
}
}
/* TODO(RECLAYER): Remove me once TLSv1.3 write side converted */
if (SSL_CONNECTION_IS_TLS13(serversc)) {
memcpy(crec_wseq_after, &clientsc->rlayer.write_sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_after, &serversc->rlayer.write_sequence, SEQ_NUM_SIZE);
} else {
memcpy(crec_wseq_after, &clientsc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_after, &serversc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
}
memcpy(crec_wseq_after, &clientsc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
memcpy(srec_wseq_after, &serversc->rlayer.wrl->sequence, SEQ_NUM_SIZE);
memcpy(crec_rseq_after, &clientsc->rlayer.rrl->sequence, SEQ_NUM_SIZE);
memcpy(srec_rseq_after, &serversc->rlayer.rrl->sequence, SEQ_NUM_SIZE);