mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-07-30 08:16:38 +08:00
Merge pull request #1619 from valeriosetti/issue1585
[development] Stale DTLS- SRTP negotiation state after session_reset() (ARM-RZ7EMQAA)
This commit is contained in:
commit
41a8bdf109
3
ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt
Normal file
3
ChangeLog.d/mbedtls_ssl_set_cid-documentation.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Bugfix
|
||||
* Fixed documentation of mbedtls_ssl_set_cid(): the set CID configuration
|
||||
is applied to all subsequent handshakes, not just to the next one.
|
||||
6
ChangeLog.d/security1585.txt
Normal file
6
ChangeLog.d/security1585.txt
Normal file
@ -0,0 +1,6 @@
|
||||
Security
|
||||
* Ensure 'badmac_seen' and 'dtls_srtp_info' fields from 'mbedtls_ssl_context'
|
||||
are properly zeroized when mbedtls_ssl_session_reset() is called. This
|
||||
could cause premature DTLS connection failure or incorrect DTLS-SRTP
|
||||
parameter inheritance for applications reusing an SSL context.
|
||||
Reported by jjfz123. CVE-2026-50585.
|
||||
@ -1 +1 @@
|
||||
Subproject commit d6dec17adfb5bf283c6a7a5bb6c451ecdc0b8201
|
||||
Subproject commit dde0c4a0e448a0552f18817dcea633bb851fd288
|
||||
@ -1324,6 +1324,15 @@ typedef union {
|
||||
void *p; /* typically a pointer to extra data */
|
||||
} mbedtls_ssl_user_data_t;
|
||||
|
||||
/**
|
||||
* Added at the end of "struct mbedtls_ssl_config" and "struct mbedtls_ssl_context"
|
||||
* to reserve a field for future use.
|
||||
*/
|
||||
typedef union {
|
||||
size_t number;
|
||||
void *ptr;
|
||||
} mbedtls_ssl_unused_data_t;
|
||||
|
||||
/**
|
||||
* SSL/TLS configuration to be shared between mbedtls_ssl_context structures.
|
||||
*/
|
||||
@ -1572,13 +1581,20 @@ struct mbedtls_ssl_config {
|
||||
const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers */
|
||||
#endif
|
||||
|
||||
/* Unused field reserved for future use */
|
||||
union {
|
||||
size_t number;
|
||||
void *ptr;
|
||||
} MBEDTLS_PRIVATE(unused);
|
||||
mbedtls_ssl_unused_data_t MBEDTLS_PRIVATE(unused);
|
||||
};
|
||||
|
||||
/*
|
||||
* Warning: whenever a change is applied to "mbedtls_ssl_context" please re-run
|
||||
* the script "tests/scripts/generate_ssl_session_reset_check.py".
|
||||
* Please note that this script has some limitation that should be considered
|
||||
* when modifing "mbedtls_ssl_context":
|
||||
* - Parsed structure must start with struct "mbedtls_ssl_context {"
|
||||
* (not "typedef struct {").
|
||||
* - It must end with "}}" in column 0.
|
||||
* - Must not contain "#else" or "#elif" conditionals.
|
||||
* - Must not contain nested struct/union/enum definitions.
|
||||
*/
|
||||
struct mbedtls_ssl_context {
|
||||
const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */
|
||||
|
||||
@ -1861,11 +1877,7 @@ struct mbedtls_ssl_context {
|
||||
*/
|
||||
mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data);
|
||||
|
||||
/* Unused field reserved for future use */
|
||||
union {
|
||||
size_t number;
|
||||
void *ptr;
|
||||
} MBEDTLS_PRIVATE(unused);
|
||||
mbedtls_ssl_unused_data_t MBEDTLS_PRIVATE(unused);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2169,7 +2181,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
|
||||
|
||||
/**
|
||||
* \brief Configure the use of the Connection ID (CID)
|
||||
* extension in the next handshake.
|
||||
* extension in subsequent handshakes.
|
||||
*
|
||||
* Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05
|
||||
* https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
|
||||
@ -2190,7 +2202,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
|
||||
* headers of outgoing messages.
|
||||
*
|
||||
* This API enables or disables the use of the CID extension
|
||||
* in the next handshake and sets the value of the CID to
|
||||
* in subsequent handshakes and sets the value of the CID to
|
||||
* be used for incoming messages.
|
||||
*
|
||||
* \param ssl The SSL context to configure. This must be initialized.
|
||||
@ -2221,11 +2233,11 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
|
||||
* successful call to this function to run the handshake.
|
||||
*
|
||||
* \note This call cannot guarantee that the use of the CID
|
||||
* will be successfully negotiated in the next handshake,
|
||||
* will be successfully negotiated in subsequent handshakes,
|
||||
* because the peer might not support it. Specifically:
|
||||
* - On the Client, enabling the use of the CID through
|
||||
* this call implies that the `ClientHello` in the next
|
||||
* handshake will include the CID extension, thereby
|
||||
* this call implies that the `ClientHello` in subsequent
|
||||
* handshakes will include the CID extension, thereby
|
||||
* offering the use of the CID to the server. Only if
|
||||
* the `ServerHello` contains the CID extension, too,
|
||||
* the CID extension will actually be put to use.
|
||||
@ -2248,7 +2260,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
|
||||
* Mbed TLS.
|
||||
*
|
||||
* \return \c 0 on success. In this case, the CID configuration
|
||||
* applies to the next handshake.
|
||||
* applies to subsequent handshakes.
|
||||
* \return A negative error code on failure.
|
||||
*/
|
||||
int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,
|
||||
|
||||
@ -1308,6 +1308,8 @@ void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl,
|
||||
ssl->in_fatal_alert_recv = 0;
|
||||
ssl->in_fatal_alert_type = 0;
|
||||
ssl->send_alert = 0;
|
||||
ssl->alert_reason = 0;
|
||||
ssl->alert_type = 0;
|
||||
|
||||
/* Reset outgoing message writing */
|
||||
ssl->out_msgtype = 0;
|
||||
@ -1357,6 +1359,8 @@ int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial)
|
||||
ssl->flags &= MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION;
|
||||
ssl->tls_version = ssl->conf->max_tls_version;
|
||||
|
||||
ssl->badmac_seen = 0;
|
||||
|
||||
mbedtls_ssl_session_reset_msg_layer(ssl, partial);
|
||||
|
||||
/* Reset renegotiation state */
|
||||
@ -1382,6 +1386,10 @@ int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial)
|
||||
ssl->alpn_chosen = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_SRTP)
|
||||
memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info));
|
||||
#endif /* MBEDTLS_SSL_DTLS_SRTP */
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
|
||||
int free_cli_id = 1;
|
||||
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
|
||||
|
||||
@ -22,6 +22,7 @@ int main(void)
|
||||
#else /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_CLI_C */
|
||||
|
||||
#include "test/psa_crypto_helpers.h"
|
||||
#include "test/ssl_helpers.h"
|
||||
|
||||
/* Size of memory to be allocated for the heap, when using the library's memory
|
||||
* management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */
|
||||
@ -2800,12 +2801,21 @@ send_request:
|
||||
memset(peer_crt_info, 0, sizeof(peer_crt_info));
|
||||
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
|
||||
|
||||
/* Dump the SSL context before resetting it. This will be used below
|
||||
* to check if the reset function worked properly. */
|
||||
mbedtls_ssl_context ssl_before = ssl;
|
||||
if ((ret = mbedtls_ssl_session_reset(&ssl)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||
(unsigned int) -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &ssl) != 0) {
|
||||
mbedtls_printf(
|
||||
" failed\n ! mbedtls_ssl_session_reset didn't properly reset ssl context\n\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
|
||||
|
||||
@ -52,6 +52,7 @@ int main(void)
|
||||
#endif
|
||||
|
||||
#include "test/psa_crypto_helpers.h"
|
||||
#include "test/ssl_helpers.h"
|
||||
|
||||
#include "mbedtls/pk.h"
|
||||
#if defined(MBEDTLS_PK_HAVE_PRIVATE_HEADER)
|
||||
@ -3271,7 +3272,15 @@ reset:
|
||||
|
||||
mbedtls_net_free(&client_fd);
|
||||
|
||||
/* Dump the SSL context before resetting it. This will be used below
|
||||
* to check if the reset function worked properly. */
|
||||
mbedtls_ssl_context ssl_before = ssl;
|
||||
mbedtls_ssl_session_reset(&ssl);
|
||||
if (mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &ssl) != 0) {
|
||||
mbedtls_printf(
|
||||
" failed\n ! mbedtls_ssl_session_reset didn't properly reset ssl context\n\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* 3. Wait until a client connects
|
||||
|
||||
@ -16,12 +16,10 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <test/helpers.h>
|
||||
#include <test/macros.h>
|
||||
#include <test/random.h>
|
||||
#include <test/psa_crypto_helpers.h>
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
#include <ssl_misc.h>
|
||||
#include <mbedtls/timing.h>
|
||||
#include <mbedtls/debug.h>
|
||||
|
||||
@ -31,10 +29,6 @@
|
||||
#include "mbedtls/ssl_cache.h"
|
||||
#endif
|
||||
|
||||
#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
|
||||
psa_to_ssl_errors, \
|
||||
psa_generic_status_to_mbedtls)
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
|
||||
#if defined(PSA_WANT_KEY_TYPE_AES)
|
||||
#if defined(PSA_WANT_ALG_GCM)
|
||||
@ -106,13 +100,6 @@
|
||||
#define MBEDTLS_TEST_HAS_ADDITIONAL_HASH
|
||||
#endif
|
||||
|
||||
enum {
|
||||
#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \
|
||||
tls13_label_ ## name,
|
||||
MBEDTLS_SSL_TLS1_3_LABEL_LIST
|
||||
#undef MBEDTLS_SSL_TLS1_3_LABEL
|
||||
};
|
||||
|
||||
#if defined(MBEDTLS_SSL_ALPN)
|
||||
#define MBEDTLS_TEST_MAX_ALPN_LIST_SIZE 10
|
||||
#endif
|
||||
@ -614,68 +601,6 @@ int mbedtls_test_move_handshake_to_state(mbedtls_ssl_context *ssl,
|
||||
|
||||
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
|
||||
|
||||
/*
|
||||
* Helper function setting up inverse record transformations
|
||||
* using given cipher, hash, EtM mode, authentication tag length,
|
||||
* and version.
|
||||
*/
|
||||
#define CHK(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
ret = -1; \
|
||||
goto cleanup; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX
|
||||
#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_IN_LEN_MAX
|
||||
#else
|
||||
#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_OUT_LEN_MAX
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
|
||||
defined(PSA_WANT_ALG_CBC_NO_PADDING) && defined(PSA_WANT_KEY_TYPE_AES)
|
||||
int mbedtls_test_psa_cipher_encrypt_helper(mbedtls_ssl_transform *transform,
|
||||
const unsigned char *iv,
|
||||
size_t iv_len,
|
||||
const unsigned char *input,
|
||||
size_t ilen,
|
||||
unsigned char *output,
|
||||
size_t *olen);
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && PSA_WANT_ALG_CBC_NO_PADDING &&
|
||||
PSA_WANT_KEY_TYPE_AES */
|
||||
|
||||
int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in,
|
||||
mbedtls_ssl_transform *t_out,
|
||||
int cipher_type, int hash_id,
|
||||
int etm, int tag_mode,
|
||||
mbedtls_ssl_protocol_version tls_version,
|
||||
size_t cid0_len,
|
||||
size_t cid1_len);
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
/**
|
||||
* \param[in,out] record The record to prepare.
|
||||
* It must contain the data to MAC at offset
|
||||
* `record->data_offset`, of length
|
||||
* `record->data_length`.
|
||||
* On success, write the MAC immediately
|
||||
* after the data and increment
|
||||
* `record->data_length` accordingly.
|
||||
* \param[in,out] transform_out The out transform, typically prepared by
|
||||
* mbedtls_test_ssl_build_transforms().
|
||||
* Its HMAC context may be used. Other than that
|
||||
* it is treated as an input parameter.
|
||||
*
|
||||
* \return 0 on success, an `MBEDTLS_ERR_xxx` error code
|
||||
* or -1 on error.
|
||||
*/
|
||||
int mbedtls_test_ssl_prepare_record_mac(mbedtls_record *record,
|
||||
mbedtls_ssl_transform *transform_out);
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
|
||||
/*
|
||||
* Populate a session structure for serialization tests.
|
||||
* Choose dummy values, mostly non-0 to distinguish from the init default.
|
||||
@ -775,23 +700,6 @@ void mbedtls_test_ssl_perform_handshake(
|
||||
const mbedtls_test_handshake_test_options *options);
|
||||
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
/*
|
||||
* Tweak vector lengths in a TLS 1.3 Certificate message
|
||||
*
|
||||
* \param[in] buf Buffer containing the Certificate message to tweak
|
||||
* \param[in]]out] end End of the buffer to parse
|
||||
* \param tweak Tweak identifier (from 1 to the number of tweaks).
|
||||
* \param[out] expected_result Error code expected from the parsing function
|
||||
* \param[out] args Arguments of the MBEDTLS_SSL_CHK_BUF_READ_PTR call that
|
||||
* is expected to fail. All zeroes if no
|
||||
* MBEDTLS_SSL_CHK_BUF_READ_PTR failure is expected.
|
||||
*/
|
||||
int mbedtls_test_tweak_tls13_certificate_msg_vector_len(
|
||||
unsigned char *buf, unsigned char **end, int tweak,
|
||||
int *expected_result, mbedtls_ssl_chk_buf_ptr_args *args);
|
||||
#endif /* MBEDTLS_TEST_HOOKS */
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
int mbedtls_test_ticket_write(
|
||||
void *p_ticket, const mbedtls_ssl_session *session,
|
||||
@ -838,6 +746,23 @@ int mbedtls_test_get_tls13_ticket(
|
||||
&psa_type, &psa_bits), \
|
||||
PSA_ERROR_NOT_SUPPORTED);
|
||||
|
||||
/**
|
||||
* Verify that mbedtls_ssl_session_reset() properly managed fields of the
|
||||
* mbedtls_ssl_context structure. The expected action on reset depends on the
|
||||
* specific field.
|
||||
*
|
||||
* Note: the code is automatically generated from the python script
|
||||
* "tests/scripts/generate_ssl_session_reset_check.py".
|
||||
*
|
||||
* \param[in] before The SSL context before mbedtls_ssl_session_reset()
|
||||
* is called on it. This is used for fields that
|
||||
* should be kept untouched during the reset.
|
||||
* \param[in] after The SSL context after mbedtls_ssl_session_reset()
|
||||
* has been called on it.
|
||||
*/
|
||||
int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context *before,
|
||||
const mbedtls_ssl_context *after);
|
||||
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
#endif /* SSL_HELPERS_H */
|
||||
|
||||
110
tests/include/test/ssl_helpers_internal.h
Normal file
110
tests/include/test/ssl_helpers_internal.h
Normal file
@ -0,0 +1,110 @@
|
||||
/** \file ssl_helpers.h
|
||||
*
|
||||
* \brief This file contains helper functions for TLS that rely on private
|
||||
* headers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef SSL_HELPERS_INTERNAL_H
|
||||
#define SSL_HELPERS_INTERNAL_H
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
#include <ssl_misc.h>
|
||||
|
||||
#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
|
||||
psa_to_ssl_errors, \
|
||||
psa_generic_status_to_mbedtls)
|
||||
|
||||
enum {
|
||||
#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \
|
||||
tls13_label_ ## name,
|
||||
MBEDTLS_SSL_TLS1_3_LABEL_LIST
|
||||
#undef MBEDTLS_SSL_TLS1_3_LABEL
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper function setting up inverse record transformations
|
||||
* using given cipher, hash, EtM mode, authentication tag length,
|
||||
* and version.
|
||||
*/
|
||||
#define CHK(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
ret = -1; \
|
||||
goto cleanup; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX
|
||||
#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_IN_LEN_MAX
|
||||
#else
|
||||
#define SSL_CID_LEN_MIN MBEDTLS_SSL_CID_OUT_LEN_MAX
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
|
||||
defined(PSA_WANT_ALG_CBC_NO_PADDING) && defined(PSA_WANT_KEY_TYPE_AES)
|
||||
int mbedtls_test_psa_cipher_encrypt_helper(mbedtls_ssl_transform *transform,
|
||||
const unsigned char *iv,
|
||||
size_t iv_len,
|
||||
const unsigned char *input,
|
||||
size_t ilen,
|
||||
unsigned char *output,
|
||||
size_t *olen);
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && PSA_WANT_ALG_CBC_NO_PADDING &&
|
||||
PSA_WANT_KEY_TYPE_AES */
|
||||
|
||||
int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in,
|
||||
mbedtls_ssl_transform *t_out,
|
||||
int cipher_type, int hash_id,
|
||||
int etm, int tag_mode,
|
||||
mbedtls_ssl_protocol_version tls_version,
|
||||
size_t cid0_len,
|
||||
size_t cid1_len);
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
/**
|
||||
* \param[in,out] record The record to prepare.
|
||||
* It must contain the data to MAC at offset
|
||||
* `record->data_offset`, of length
|
||||
* `record->data_length`.
|
||||
* On success, write the MAC immediately
|
||||
* after the data and increment
|
||||
* `record->data_length` accordingly.
|
||||
* \param[in,out] transform_out The out transform, typically prepared by
|
||||
* mbedtls_test_ssl_build_transforms().
|
||||
* Its HMAC context may be used. Other than that
|
||||
* it is treated as an input parameter.
|
||||
*
|
||||
* \return 0 on success, an `MBEDTLS_ERR_xxx` error code
|
||||
* or -1 on error.
|
||||
*/
|
||||
int mbedtls_test_ssl_prepare_record_mac(mbedtls_record *record,
|
||||
mbedtls_ssl_transform *transform_out);
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
/*
|
||||
* Tweak vector lengths in a TLS 1.3 Certificate message
|
||||
*
|
||||
* \param[in] buf Buffer containing the Certificate message to tweak
|
||||
* \param[in]]out] end End of the buffer to parse
|
||||
* \param tweak Tweak identifier (from 1 to the number of tweaks).
|
||||
* \param[out] expected_result Error code expected from the parsing function
|
||||
* \param[out] args Arguments of the MBEDTLS_SSL_CHK_BUF_READ_PTR call that
|
||||
* is expected to fail. All zeroes if no
|
||||
* MBEDTLS_SSL_CHK_BUF_READ_PTR failure is expected.
|
||||
*/
|
||||
int mbedtls_test_tweak_tls13_certificate_msg_vector_len(
|
||||
unsigned char *buf, unsigned char **end, int tweak,
|
||||
int *expected_result, mbedtls_ssl_chk_buf_ptr_args *args);
|
||||
#endif /* MBEDTLS_TEST_HOOKS */
|
||||
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
#endif /* SSL_HELPERS_INTERNAL_H */
|
||||
118
tests/scripts/generate_ssl_session_reset_check.py
Executable file
118
tests/scripts/generate_ssl_session_reset_check.py
Executable file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate test code to validate mbedtls_ssl_session_reset().
|
||||
"""
|
||||
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
|
||||
import scripts_path # pylint: disable=unused-import
|
||||
from mbedtls_framework import ssl_session_reset_check
|
||||
|
||||
RULES = {
|
||||
'conf': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'state': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'flags': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'renego_status': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'renego_records_seen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'tls_version': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'early_data_state': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'badmac_seen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'f_vrfy': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'p_vrfy': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'f_send': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'f_recv': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'f_recv_timeout': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'p_bio': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'session_in': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'session_out': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'session': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'session_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'handshake': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'transform_in': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'transform_out': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'transform': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'transform_negotiate': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'transform_application': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'p_timer': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'f_set_timer': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'f_get_timer': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'in_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_len': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'in_offt': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_msgtype': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_msglen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_left': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'in_epoch': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'next_record_offset': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_window_top': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_window': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_hslen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_hsfraglen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'nb_zero': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'keep_current_message': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_fatal_alert_recv': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_fatal_alert_type': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'send_alert': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'alert_type': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'alert_reason': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'disable_datagram_packing': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'discard_early_data_record': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'total_early_data_size': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'out_buf': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_ctr': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_hdr': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_cid': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_len': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_iv': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_msg': ssl_session_reset_check.ResetBehavior.REALLOCATE,
|
||||
'out_msgtype': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'out_msglen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'out_left': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'out_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'cur_out_ctr': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'mtu': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'hostname': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'alpn_chosen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'dtls_srtp_info': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'cli_id': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'cli_id_len': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'secure_renegotiation': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'verify_data_len': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'own_verify_data': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'peer_verify_data': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'own_cid': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'own_cid_len': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'negotiate_cid': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'f_export_keys': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'p_export_keys': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'user_data': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'unused': ssl_session_reset_check.ResetBehavior.IGNORE,
|
||||
}
|
||||
|
||||
SPECIAL_BEHAVIORS = {
|
||||
'flags': ['TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), ' +
|
||||
'initial.flags);',
|
||||
'TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), ' +
|
||||
'(after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));'],
|
||||
'tls_version': ['TEST_ASSERT(after->tls_version == after->conf->max_tls_version);'],
|
||||
'user_data': ['TEST_ASSERT(before->user_data.n == after->user_data.n);'],
|
||||
'in_buf_len': ['TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);'],
|
||||
'out_buf_len': ['TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);'],
|
||||
}
|
||||
|
||||
NAMED_STRUCTURES = frozenset([
|
||||
'dtls_srtp_info',
|
||||
])
|
||||
|
||||
FIELDS_INFO = ssl_session_reset_check.FieldsInfo(RULES,
|
||||
SPECIAL_BEHAVIORS,
|
||||
NAMED_STRUCTURES)
|
||||
|
||||
if __name__ == '__main__':
|
||||
ssl_session_reset_check.main(FIELDS_INFO)
|
||||
190
tests/src/ssl_context_reset_verifier.c
Normal file
190
tests/src/ssl_context_reset_verifier.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following function was automatically generated through the script
|
||||
* ./tests/scripts/generate_ssl_session_reset_check.py.
|
||||
*/
|
||||
|
||||
#include <test/ssl_helpers.h>
|
||||
#include <test/ssl_helpers_internal.h>
|
||||
#include "mbedtls/psa_util.h"
|
||||
#include <test/macros.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
|
||||
int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context *before,
|
||||
const mbedtls_ssl_context *after)
|
||||
{
|
||||
mbedtls_ssl_context initial;
|
||||
int ret = -1;
|
||||
|
||||
/* Create a freshly initialized SSL context*/
|
||||
memset(&initial, 0, sizeof(initial));
|
||||
mbedtls_ssl_init(&initial);
|
||||
TEST_EQUAL(mbedtls_ssl_setup(&initial, after->conf), 0);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
TEST_ASSERT(before->conf == after->conf);
|
||||
TEST_ASSERT(after->state == initial.state);
|
||||
TEST_EQUAL((after->flags & ~(MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION)), initial.flags);
|
||||
TEST_EQUAL((before->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION), (after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
TEST_ASSERT(after->renego_status == initial.renego_status);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
TEST_ASSERT(after->renego_records_seen == initial.renego_records_seen);
|
||||
#endif
|
||||
TEST_ASSERT(after->tls_version == after->conf->max_tls_version);
|
||||
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
|
||||
TEST_ASSERT(after->early_data_state == initial.early_data_state);
|
||||
#endif
|
||||
TEST_ASSERT(after->badmac_seen == initial.badmac_seen);
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
TEST_ASSERT(before->f_vrfy == after->f_vrfy);
|
||||
#endif
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
TEST_ASSERT(before->p_vrfy == after->p_vrfy);
|
||||
#endif
|
||||
TEST_ASSERT(before->f_send == after->f_send);
|
||||
TEST_ASSERT(before->f_recv == after->f_recv);
|
||||
TEST_ASSERT(before->f_recv_timeout == after->f_recv_timeout);
|
||||
TEST_ASSERT(before->p_bio == after->p_bio);
|
||||
TEST_ASSERT(after->session_in == initial.session_in);
|
||||
TEST_ASSERT(after->session_out == initial.session_out);
|
||||
TEST_ASSERT(after->session == initial.session);
|
||||
TEST_ASSERT(after->session_negotiate != NULL);
|
||||
TEST_ASSERT(after->handshake != NULL);
|
||||
TEST_ASSERT(after->transform_in == initial.transform_in);
|
||||
TEST_ASSERT(after->transform_out == initial.transform_out);
|
||||
TEST_ASSERT(after->transform == initial.transform);
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
TEST_ASSERT(after->transform_negotiate != NULL);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
|
||||
TEST_ASSERT(after->transform_application == initial.transform_application);
|
||||
#endif
|
||||
TEST_ASSERT(before->p_timer == after->p_timer);
|
||||
TEST_ASSERT(before->f_set_timer == after->f_set_timer);
|
||||
TEST_ASSERT(before->f_get_timer == after->f_get_timer);
|
||||
TEST_ASSERT(after->in_buf != NULL);
|
||||
TEST_ASSERT(after->in_ctr != NULL);
|
||||
TEST_ASSERT(after->in_hdr != NULL);
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
TEST_ASSERT(after->in_cid != NULL);
|
||||
#endif
|
||||
TEST_ASSERT(after->in_len != NULL);
|
||||
TEST_ASSERT(after->in_iv != NULL);
|
||||
TEST_ASSERT(after->in_msg != NULL);
|
||||
TEST_ASSERT(after->in_offt == initial.in_offt);
|
||||
TEST_ASSERT(after->in_msgtype == initial.in_msgtype);
|
||||
TEST_ASSERT(after->in_msglen == initial.in_msglen);
|
||||
TEST_ASSERT(after->in_left == initial.in_left);
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
TEST_ASSERT(after->in_epoch == initial.in_epoch);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
TEST_ASSERT(after->next_record_offset == initial.next_record_offset);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
|
||||
TEST_ASSERT(after->in_window_top == initial.in_window_top);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
|
||||
TEST_ASSERT(after->in_window == initial.in_window);
|
||||
#endif
|
||||
TEST_ASSERT(after->in_hslen == initial.in_hslen);
|
||||
TEST_ASSERT(after->in_hsfraglen == initial.in_hsfraglen);
|
||||
TEST_ASSERT(after->nb_zero == initial.nb_zero);
|
||||
TEST_ASSERT(after->keep_current_message == initial.keep_current_message);
|
||||
TEST_ASSERT(after->in_fatal_alert_recv == initial.in_fatal_alert_recv);
|
||||
TEST_ASSERT(after->in_fatal_alert_type == initial.in_fatal_alert_type);
|
||||
TEST_ASSERT(after->send_alert == initial.send_alert);
|
||||
TEST_ASSERT(after->alert_type == initial.alert_type);
|
||||
TEST_ASSERT(after->alert_reason == initial.alert_reason);
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
TEST_EQUAL(before->disable_datagram_packing, after->disable_datagram_packing);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_EARLY_DATA)
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
TEST_ASSERT(after->discard_early_data_record == initial.discard_early_data_record);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_EARLY_DATA)
|
||||
TEST_ASSERT(after->total_early_data_size == initial.total_early_data_size);
|
||||
#endif
|
||||
TEST_ASSERT(after->out_buf != NULL);
|
||||
TEST_ASSERT(after->out_ctr != NULL);
|
||||
TEST_ASSERT(after->out_hdr != NULL);
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
TEST_ASSERT(after->out_cid != NULL);
|
||||
#endif
|
||||
TEST_ASSERT(after->out_len != NULL);
|
||||
TEST_ASSERT(after->out_iv != NULL);
|
||||
TEST_ASSERT(after->out_msg != NULL);
|
||||
TEST_ASSERT(after->out_msgtype == initial.out_msgtype);
|
||||
TEST_ASSERT(after->out_msglen == initial.out_msglen);
|
||||
TEST_ASSERT(after->out_left == initial.out_left);
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
#endif
|
||||
TEST_MEMORY_COMPARE(after->cur_out_ctr, sizeof(after->cur_out_ctr), initial.cur_out_ctr, sizeof(initial.cur_out_ctr));
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
TEST_EQUAL(before->mtu, after->mtu);
|
||||
#endif
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
TEST_ASSERT(before->hostname == after->hostname);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_ALPN)
|
||||
TEST_ASSERT(after->alpn_chosen == initial.alpn_chosen);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_SRTP)
|
||||
TEST_MEMORY_COMPARE(&(after->dtls_srtp_info), sizeof(after->dtls_srtp_info), &(initial.dtls_srtp_info), sizeof(initial.dtls_srtp_info));
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
|
||||
TEST_ASSERT(after->cli_id == initial.cli_id);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
|
||||
TEST_ASSERT(after->cli_id_len == initial.cli_id_len);
|
||||
#endif
|
||||
TEST_ASSERT(after->secure_renegotiation == initial.secure_renegotiation);
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
TEST_ASSERT(after->verify_data_len == initial.verify_data_len);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
TEST_MEMORY_COMPARE(after->own_verify_data, sizeof(after->own_verify_data), initial.own_verify_data, sizeof(initial.own_verify_data));
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
TEST_MEMORY_COMPARE(after->peer_verify_data, sizeof(after->peer_verify_data), initial.peer_verify_data, sizeof(initial.peer_verify_data));
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
TEST_MEMORY_COMPARE(before->own_cid, sizeof(before->own_cid), after->own_cid, sizeof(after->own_cid));
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
TEST_EQUAL(before->own_cid_len, after->own_cid_len);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
TEST_EQUAL(before->negotiate_cid, after->negotiate_cid);
|
||||
#endif
|
||||
TEST_ASSERT(before->f_export_keys == after->f_export_keys);
|
||||
TEST_ASSERT(before->p_export_keys == after->p_export_keys);
|
||||
TEST_ASSERT(before->user_data.n == after->user_data.n);
|
||||
/* unused is ignored */
|
||||
/* *INDENT-ON* */
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
mbedtls_ssl_free(&initial);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
@ -9,6 +9,8 @@
|
||||
*/
|
||||
|
||||
#include <test/ssl_helpers.h>
|
||||
#include <test/ssl_helpers_internal.h>
|
||||
#include <test/macros.h>
|
||||
#include "mbedtls/psa_util.h"
|
||||
|
||||
#include <limits.h>
|
||||
@ -1033,6 +1035,17 @@ int mbedtls_test_ssl_endpoint_init(
|
||||
void mbedtls_test_ssl_endpoint_free(
|
||||
mbedtls_test_ssl_endpoint *ep)
|
||||
{
|
||||
// mbedtls_ssl_session_reset() requires the SSL to be setup.
|
||||
if (ep->ssl.conf != NULL) {
|
||||
mbedtls_ssl_context ssl_before;
|
||||
|
||||
/* Dump the SSL context before resetting it */
|
||||
memcpy(&ssl_before, &(ep->ssl), sizeof(mbedtls_ssl_context));
|
||||
|
||||
mbedtls_ssl_session_reset(&(ep->ssl));
|
||||
/* Check that required fields were properly reset */
|
||||
mbedtls_test_ssl_check_context_after_session_reset(&ssl_before, &(ep->ssl));
|
||||
}
|
||||
mbedtls_ssl_free(&(ep->ssl));
|
||||
mbedtls_ssl_config_free(&(ep->conf));
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <ssl_tls13_keys.h>
|
||||
#include <ssl_tls13_invasive.h>
|
||||
#include <test/ssl_helpers.h>
|
||||
#include <test/ssl_helpers_internal.h>
|
||||
|
||||
#include <constant_time_internal.h>
|
||||
#include <test/constant_flow.h>
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <ssl_misc.h>
|
||||
#include <test/ssl_helpers.h>
|
||||
#include <test/ssl_helpers_internal.h>
|
||||
|
||||
/* END_HEADER */
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user